Android 開發日誌之LBS相關開發

   根據公司業務需求的展開,需要接入地圖,並且在地圖上畫軌跡曲線以及自定義畫區域等等。地圖api可以接入百度,高德,或者google。下面以項目接入的高德地圖api爲例;

高德開放平臺文檔:https://lbs.amap.com/api/webservice/guide/create-project/get-key

按照項目具體需求下載相應的SDK,放入項目libs中;

(注意爲了兼容不同手機配置的地圖.so文件比較多,而.so文件比較大,爲了控制包大小,可以放棄部分兼容,這涉及到包大小優化,在文章裏面有講到 https://blog.csdn.net/and_caicai/article/details/105508306

1.配置 AndroidManifest.xml 文件

在AndroidManifest.xml的application標籤中配置Key:(key需要在高德開放平臺創建項目獲得)

<meta-data
    android:name="com.amap.api.v2.apikey"
    android:value="您的Key"/>

2.在AndroidManifest.xml中配置權限:

//地圖包、搜索包需要的基礎權限 <!--允許程序打開網絡套接字--> <uses-permission android:name="android.permission.INTERNET" /> <!--允許程序設置內置sd卡的寫權限--> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <!--允許程序獲取網絡狀態--> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <!--允許程序訪問WiFi網絡信息--> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <!--允許程序讀寫手機狀態和身份--> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <!--允許程序訪問CellID或WiFi熱點來獲取粗略的位置--> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

3.配置XML佈局文件  在佈局xml文件中添加地圖控件;

<com.amap.api.maps.MapView
    android:id="@+id/map"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
</com.amap.api.maps.MapView>

4..地圖展示

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.basicmap_activity);//設置對應的XML佈局文件
    
    MapView mapView = (MapView) findViewById(R.id.map);
    mapView.onCreate(savedInstanceState);// 此方法必須重寫
    AMap aMap = mapView.getMap();
    
}

5.地圖顯示時候的一些設置

	    mMapTracking.onCreate(savedInstanceState);// 此方法須覆寫。
		//地圖
		if (mAMap == null) {
			mAMap = mMapTracking.getMap();
		}
		UiSettings mUiSettings = mAMap.getUiSettings();
		mUiSettings.setZoomGesturesEnabled(true);//設置地圖是否可以手勢縮放大小
		mUiSettings.setScrollGesturesEnabled(true);//設置地圖是否可以手勢滑動
		mUiSettings.setMyLocationButtonEnabled(false);// 設置默認定位按鈕是否顯示
		mUiSettings.setZoomControlsEnabled(false);//設置地圖默認的縮放按鈕是否顯示
		mUiSettings.setLogoBottomMargin(-100);//隱藏logo
		mAMap.moveCamera(CameraUpdateFactory.zoomTo(8));

		/*將GPS定位座標類型轉換爲高德*/
		CoordinateConverter converter = new CoordinateConverter(context);
		// CoordType.GPS 待轉換座標類型
		converter.from(CoordinateConverter.CoordType.GPS);

在這裏需要提一句,

* WGS84: Google Earth採用,Google Map中國範圍外使用
* GCJ02: 火星座標系,中國國家測繪局制定的座標系統,由WGS84機密後的座標。Google Map中國和搜搜地圖使用,高德
* BD09:百度座標,GCJ02機密後的座標系
* 搜狗座標系,圖吧座標等,估計也是在GCJ02基礎上加密而成的

百度地圖 高德地圖座標系不同,通過接口獲得數據點 如果是不同座標系需要進行轉換。

6.根據座標獲取具體位置

   //異步查詢座標
  private void getAddressByLatlng(LatLng latLng) {
		//逆地理編碼查詢條件:逆地理編碼查詢的地理座標點、查詢範圍、座標類型。
		LatLonPoint latLonPoint = new LatLonPoint(latLng.latitude, latLng.longitude);
		RegeocodeQuery query = new RegeocodeQuery(latLonPoint, 500f, GeocodeSearch.AMAP);
		//異步查詢
		geocodeSearch.getFromLocationAsyn(query);
	}



    //異步查詢結果監聽
    geocodeSearch = new GeocodeSearch(context);
	geocodeSearch.setOnGeocodeSearchListener(new GeocodeSearch.OnGeocodeSearchListener() {
			@Override
			public void onRegeocodeSearched(RegeocodeResult regeocodeResult, int i) {//得到逆地理編碼異步查詢結果
				RegeocodeAddress regeocodeAddress = regeocodeResult.getRegeocodeAddress();
				String formatAddress = regeocodeAddress.getFormatAddress();
				simpleAddress = formatAddress.substring(9);
				if(!Tools.isEmpty(simpleAddress)){
					tv_out_address.setText(simpleAddress+"");
				}else{
					tv_out_address.setText("");
				}
				DLog.e("LocusFragment","查詢經緯度對應詳細地址:\n" + simpleAddress);
			}

			@Override
			public void onGeocodeSearched(GeocodeResult geocodeResult, int i) {

			}
		});

7.根據獲取的點在地圖上畫軌跡曲線(及自定義畫線)

	/*車輛行駛軌跡*/
	private void setMapTracking(final List<GPSDataBean> gpsDataList, RealTimeTruckBean bean) {
		List<Integer> colorList=new ArrayList<>();
		List<LatLng> latList=new ArrayList<>();
		mPolylineOptions = new PolylineOptions();
		mPolylineOptions.width(10);
		mPolylineOptions.zIndex(10f);
		markerOption = new MarkerOptions();
		if (NotNull.isNotNull(bean)) {
			//			addTruckOnTimeMarker(bean);
		}

		mAMap.setOnMarkerClickListener(new AMap.OnMarkerClickListener() {
			@Override
			public boolean onMarkerClick(Marker marker) {
				LatLng latLngMarker = new LatLng(marker.getPosition().latitude, marker.getPosition().longitude);
				newbounds.include(latLngMarker);
				CameraUpdate mCameraUpdate = CameraUpdateFactory.newLatLngBounds(newbounds.build(), 15);
				//加上這句好像點擊mark後不能顯示在屏幕內
				// mAMap.animateCamera(mCameraUpdate);
				return false;
			}
		});

		mAMap.setOnInfoWindowClickListener(new AMap.OnInfoWindowClickListener() {
			@Override
			public void onInfoWindowClick(Marker marker) {
				marker.hideInfoWindow();
			}
		});
		if (!NotNull.isNotNull(gpsDataList) || gpsDataList.size() <= 0) {
			mHandler.post(new Runnable() {
				@Override
				public void run() {
					showTips("無GPS數據");
					closeProgressDialog();
				}
			});

			if (bean != null) {
				if (NotNull.isNotNull(bean.getY()) && NotNull.isNotNull(bean.getX())) {
					LatLng mCenterLatLng = new LatLng(Double.parseDouble(bean.getY()), Double.parseDouble(bean.getX()));
					CameraUpdate mCameraUpdate = CameraUpdateFactory.newCameraPosition(new CameraPosition(mCenterLatLng, 10, 0, 0));
					mAMap.animateCamera(mCameraUpdate);
				}
			}
			return;
		}
		double x=0;
		double y=0;
		for (int i = 0; i < gpsDataList.size(); i++) {
			// sourceLatLng待轉換座標點 LatLng類型
			if (NotNull.isNotNull(gpsDataList.get(i).getY())&& NotNull.isNotNull(gpsDataList.get(i).getX())){
				LatLng sourceLatLng = new LatLng(Double.parseDouble(gpsDataList.get(i).getY()), Double.parseDouble(gpsDataList.get(i).getX()));
				converter.coord(sourceLatLng);
				// 執行轉換操作
				LatLng desLatLng = converter.convert();
				latList.add(desLatLng);
				colorList.add(getColorList(gpsDataList.get(i)));
				 x += sourceLatLng.latitude;
				 y += sourceLatLng.longitude;


				if (i == 0) {
					converter.coord(new LatLng(Double.parseDouble(gpsDataList.get(0).getY()), Double.parseDouble(gpsDataList.get(0).getX())));
					// 執行轉換操作
					LatLng startLatLng = converter.convert();
					markerOption.position(startLatLng);
					if (NotNull.isNotNull(gpsDataList.get(0).getWeight())) {
						double gpsDataWeight = Double.parseDouble(gpsDataList.get(0).getWeight());
						gpsWeightStart = myformat.format(gpsDataWeight);
					}

					markerOption.title("設備ID:" + truckModel.getDeviceId() + "\n車牌號:" + truckModel.getCarNumber() + "\n車重:" + gpsWeightStart + "(噸)").snippet("日期:" + gpsDataList.get(0).getDate());
					markerOption.icon(BitmapDescriptorFactory.fromBitmap(BitmapFactory.decodeResource(getResources(), R.mipmap.start)));
				} else if (i == gpsDataList.size() - 1) {
					converter.coord(new LatLng(Double.parseDouble(gpsDataList.get(gpsDataList.size() - 1).getY()), Double.parseDouble(gpsDataList.get(gpsDataList.size() - 1).getX())));
					// 執行轉換操作
					LatLng endtLatLng = converter.convert();
					markerOption.position(endtLatLng);
					if (NotNull.isNotNull(gpsDataList.get(gpsDataList.size() - 1).getWeight())) {
						double gpsDataWeight = Double.parseDouble(gpsDataList.get(gpsDataList.size() - 1).getWeight());
						gpsWeightEnd = myformat.format(gpsDataWeight);
					}
					markerOption.title("設備ID:" + truckModel.getDeviceId() + "\n車牌號:" + truckModel.getCarNumber() + "\n車重:" + gpsWeightEnd + "(噸)").snippet("日期:" + gpsDataList.get(i).getDate());
					markerOption.icon(BitmapDescriptorFactory.fromBitmap(BitmapFactory.decodeResource(getResources(), R.mipmap.end)));
				}
				markerOption.setFlat(true);
				mAMap.addMarker(markerOption);
				newbounds.include(desLatLng);//軌跡全部顯示在屏幕內
			}
		}
		CameraUpdate mCameraUpdate = CameraUpdateFactory.newLatLng(new LatLng((double) (x/gpsDataList.size()),(double)(y/gpsDataList.size())));
		mAMap.animateCamera(mCameraUpdate);//第二個參數爲四周留空寬度.
		mAMap.setMinZoomLevel(6f);
		mAMap.setMaxZoomLevel(13f);
		mAMap.moveCamera(CameraUpdateFactory.zoomTo(8));
		mPolylineOptions.addAll(latList);
		mPolylineOptions.colorValues(colorList);
		mAMap.addPolyline(mPolylineOptions);
	
	}

如果有類似如上圖的軌跡曲線,曲線點沒有依附在道路上,可以嘗試用 高德的軌跡糾偏

https://lbs.amap.com/api/android-sdk/guide/draw-on-map/track-sdk  

8.在地圖上顯示實時位置,並用圖標標記


	//添加實時位置
	private void addAddr(MarkerOptions opt, OnLineTruckBean bean, String speed) {
		if (NotNull.isNotNull(bean.getY()) && NotNull.isNotNull(bean.getX())) {
			if (addMarker != null) {
				addMarker.remove();
			}
			float zoom= mAMap.getCameraPosition().zoom;
			if(zoom <4){
				zoom=10f;
			}
			Bitmap bitmap = doAddBit(bean,speed);//圖標
			LatLng gpsLatLng = new LatLng(Double.parseDouble(bean.getY()), Double.parseDouble(bean.getX()));//當前座標(x,y)
			converter.coord(gpsLatLng);
			// 執行轉換操作
			LatLng gdlatLng = converter.convert();
			opt.position(gdlatLng);

		
			opt.icon(BitmapDescriptorFactory.fromBitmap(bitmap));
			addMarker = mAMap.addMarker(opt);
			newbounds.include(gdlatLng);//軌跡全部顯示在屏幕內

			CameraUpdate mCameraUpdate = CameraUpdateFactory.changeLatLng(gdlatLng);//改變位置
			mAMap.moveCamera(mCameraUpdate);//第二個參數爲四周留空寬度.
			mAMap.moveCamera(CameraUpdateFactory.zoomTo(zoom));
		
		}
	}

9.在地圖自定義區域 圓或者多邊形

  //畫圓,圓心座標(lat1,lon) 半徑r3    
  Double lat1 = Double.parseDouble(lat);
                                    Double lon2 = Double.parseDouble(lon);
                                    Double r3 = Double.parseDouble(r);
                                    LatLng latLng = new LatLng(lat1,lon2);
                                    Circle myCircle=mAMap.addCircle(new CircleOptions().
                                            center(latLng).
                                            radius(r3).
                                            fillColor(Color.argb(170, 238, 89, 83)).
                                            strokeColor(Color.argb(170, 13, 130, 235)).
                                            strokeWidth(3f));
//畫多邊形   
List<WeiLan> wllis  =jsonToBeanList(data,WeiLan.class); //點list
                                List<LatLng>  list3=new ArrayList<>();
                                for (int i = 0; i < wllis.size(); i++) {
                                    WeiLan point = wllis.get(i);
                                    Double lat1 = Double.parseDouble(point.getLat());
                                    Double lat2 = Double.parseDouble(point.getLng());
                                    LatLng lat = new LatLng(lat1, lat2);
                                    list3.add(lat);
                                    llis.add(lat);
                                }
                                // 聲明 多邊形參數對象
                                PolygonOptions polygonOptions = new PolygonOptions();
                                // 添加 多邊形的每個頂點(順序添加)
                                for (int t = 0; t < list3.size(); t++) {
                                    LatLng latp = list3.get(t);
                                    polygonOptions.add(latp);
                                }
                                polygonOptions.strokeWidth(4) // 多邊形的邊框 深綠色:#98ED84
                                        .strokeColor(Color.argb(100, 13, 130, 235)) // 邊框顏色
                                        .fillColor(Color.argb(100, 238, 89, 83));   // 多邊形的填充色
                          
                                mAMap.addPolygon(polygonOptions);

 

效果圖如下:

 

以上代碼涉及的項目可以再github上查看:https://github.com/ctgu1988/hd_wnq-yufeng

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章