根據公司業務需求的展開,需要接入地圖,並且在地圖上畫軌跡曲線以及自定義畫區域等等。地圖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