天地圖之定位資訊詳解
最近的專案涉及到百度地圖的使用,專案組通知使用天地圖替代百度地圖,一個原因是天地圖是國家測繪地理資訊局建設的,企業可以使用其公眾版本進行開發以提供相關的地圖資訊服務,較其他地圖具有權威性,當然天地圖提供的服務是否較其他地圖更具有權威性和實時性,這個作為普通開發者是不能確定的,另一個原因是減少運用成本,我覺得是否真能達到這樣的目標真不一定,畢竟商業地圖輸出能力還是較免費版本更強。還是先來開始天地圖 Android SDK 的學習之路吧,先從一下幾個方面來學習:
- 引入天地圖 SDK
- 地圖顯示
- 我的位置
- 定點陣圖標的修改
- 獲取位置資訊
- 顯示效果
引入天地圖 SDK
首先下載天地圖地圖 SDK,然後新增相應的 Jar 包和 so 檔案到 libs 資料夾中,在 module 的 build.gradle 檔案中指定 so 檔案的目錄為 libs 目錄,具體如下:
sourceSets {
main {
//指定so檔案的查詢目錄是libs目錄
jniLibs.srcDir 'libs'
}
}
按照官網指定的許可權配置,使用過程中發現少了許可權,下面是完整許可權列表,具體如下:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
如果專案 targetSdkVersion 是 23 以上記得動態申請相關危險許可權,此時,天地圖地圖 SDK 就引入到專案中了。
地圖顯示
首先在佈局中引入 MapView,佈局程式碼如下:
<com.tianditu.android.maps.MapView
android:id="@+id/mapView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
此時,地圖就可以正常顯示了,不需要額外的配置,當然可以初始化地圖相關的一些引數,常用配置如下:
private void initMapView() {
//啟用內建的縮放元件
mapView.setBuiltInZoomControls(true);
//得到MapView的控制權,可以用它控制和驅動平移和縮放
mMapController = mapView.getController();
//用給定的經緯度構造一個GeoPoint,單位是微度 (度 * 1E6)
GeoPoint point = new GeoPoint((int) (39.915 * 1E6), (int) (116.404 * 1E6));
//設定地圖中心點
mMapController.setCenter(point);
//設定地圖縮放級別
mMapController.setZoom(12);
}
天地圖 Android SDK 的引入及地圖顯示相對百度地圖、高德地圖還是比較方便的。
我的位置
開發中常常需要定位當前位置,並且要從之前的位置動畫移動到當前位置,獲取我的位置的關鍵類是 MyLocationOverlay ,通過該類可以輕鬆獲取我的位置,由於該類是 Overlay 的子類,在啟用我的位置後要將該類的例項新增到 MapView 中,我的位置才會正確顯示,至於移動到當前位置使用到 MapController 這個類,從MapView 中獲取到地圖控制器就可以移動到我的位置了,程式碼參考如下:
//建立MyLocationOverlay
myLocationOverlay = new MyLocationOverlay(this, mapView);
//啟用指南針位置更新
myLocationOverlay.enableCompass();
//啟用我的位置
myLocationOverlay.enableMyLocation();
mapView.addOverlay(myLocationOverlay);
//獲得當前位置
mPoint = myLocationOverlay.getMyLocation();
//動畫移動到當前位置
mMapController.animateTo(mPoint);
我的位置定位成功,那麼如何修改預設的定點陣圖標呢,下面告訴你如何修改預設的定點陣圖標。
定點陣圖標修改
天地圖預設定點陣圖標是一個藍色的小圓點圖示,很多時候都會遇到修改定點陣圖標以及誤差半徑的修改,後者主要會顯示一個帶陰影的圓圈,以此來表示當前定位的誤差範圍,關於定位主要涉及到的類是 MyLocationOverlay,這個類是一個位置覆蓋類,主要負責繪製、獲取我的位置以及指南針的顯示等,那麼如何修改這個預設的定點陣圖標呢,下面是一點思路:
- 在專案路徑中找到預設定點陣圖標;
- 在關鍵類中找到設定該預設圖示的位置;
- 繼承關鍵類,重寫相關程式碼,替換原有的定點陣圖標為新的定點陣圖標;
- 使用新的類替換 MyLocationOverlay 類。
這種修改方式基本適用於類似的修改預設圖示的場景,關鍵一點是找到相關類及相關位置然後做一下替換工作就 OK 了,當然這裡對應的就是繼承 MyLocationOverlay,重寫 drawMyLocation 方法,然後替換相應圖示,關鍵程式碼如下:
@Override
protected void drawMyLocation(GL10 gl, MapView mapView, Location lastFix, GeoPoint myLocation, long when) {
//獲得螢幕座標
Point point = new Point();
mapView.getProjection().toPixels(myLocation,point);
//預設精度
float accuracy = getAccuracy();
//指定精度
float accuracy = 500;
//獲得實際誤差距離
float distance = mapView.getProjection().metersToEquatorPixels(accuracy);
AndroidJni.OpenglFillRound(point.x, point.y, (int)distance, 0, 360, 137, 170, 213, 77);
//建立Drawable
UtilTextureDrawable drawable = new UtilTextureDrawable(mContext, R.drawable.ic_location, BOUND_TYPE_CENTER);
drawable.DrawTexture(gl,point,0.0F);
}
此時,使用自定義的 MLocationOverlay 替換 MyLocationOverlay 啟用我的位置,定點陣圖標已經被更改了,這裡預設定點陣圖標修改的另一種思路是獲取到當前位置後,使用 Marker 設定標註來實現自己定義的定點陣圖標,實踐發現是沒有問題的,但是這樣誤差範圍就不能夠輕鬆實現了,綜上,還是上一種思路比較好,一勞永逸的解決自定義圖示的修改。
獲取位置資訊
這裡獲取具體的位置資訊,需要設定逆地理編碼回撥結果的監聽獲取詳細地址資訊,設定座標位置,開始搜尋地址,先實現逆地理編碼結果監聽器,程式碼如下:
/**
* 逆地理編碼回撥結果監聽
*/
class OnGeoResultListener implements TGeoDecode.OnGeoResultListener {
@Override
public void onGeoDecodeResult(TGeoAddress tGeoAddress, int errorCode) {
if (TErrorCode.OK == errorCode) {
// 查詢點相關資訊
String str = "最近的 poi 名稱:" + tGeoAddress.getPoiName() + "\n";
str += "查詢點 Poi 點的方位:" + tGeoAddress.getPoiDirection() + "\n";
str += "查詢點 Poi 點的距離:" + tGeoAddress.getPoiDistance() + "\n";
str += "查詢點行政區名稱:" + tGeoAddress.getCity() + "\n";
str += "查詢點地理描述全稱:" + tGeoAddress.getFullName() + "\n";
str += "查詢點的地址:" + tGeoAddress.getAddress() + "\n";
str += "查詢點的方位:" + tGeoAddress.getAddrDirection() + "\n";
str += "查詢點的距離:" + tGeoAddress.getAddrDistance() + "\n";
str += "查詢點道路名稱:" + tGeoAddress.getRoadName() + "\n";
str += "查詢點與最近道路的距離:" + tGeoAddress.getRoadDistance();
tvAddress.setText(tGeoAddress.getFullName());
System.out.println(str);
} else {
System.out.println("查詢出錯:" + errorCode);
}
}
}
然後,設定對逆地理編碼結果的監聽,程式碼參考如下:
//逆地理編碼類,根據輸入的點座標,返回相應的地理資訊
TGeoDecode tGeoDecode = new TGeoDecode(new OnGeoResultListener());
tGeoDecode.search(mPoint);
如果前面都沒有問題,那麼具體的位置資訊肯定沒有問題,只是沒有提供獲取當前城市名稱的方法,getCity() 返回的是行政區名稱而不是當前城市名稱,這一定對於只想定位當前城市的需求就不友好了,關於天地圖的初次接觸就到此為止了。
顯示效果
注意兩次修改前和修改後的圖示以及誤差範圍的顯示,下面是顯示效果,具體如下:
實際上地圖的使用大同小異,通過以上內容基本需求已經能夠完成,當然地圖開發中還有一塊內容是地圖標註,這一步內容陸續推送出來,可以新增我的微信 jamanu 互相交流學習。