效果圖
前言
爲什麼調用第三方呢?集成在App裏面不行嗎?
- 接入導航SDK,以百度爲例,apk包體積能增加小几十兆之多,上一版本還是幾兆的apk,迭代一版本直接幾十兆了,落差之大,難以接受。
- 雖說當下流量不值錢了,但是下載時長越久,客戶丟失率越高。
- 最關鍵的是,當下地圖並非一家獨大,客戶應該有自主選擇的權利,你集成了百度,但用戶卻鍾愛於高德,這極爲尷尬。
- 且當下包括微信等一衆主流App都是通過調用第三方地圖來做的,這顯然有一定道理,也是大勢所趨。
- 坑多,顯然是幹不過別人一個團隊專門來做地圖的,不如站在巨人的肩上。
綜上所訴,優點顯而易見。
座標系
有地圖就有經緯度,有經緯度就扯到座標系,簡單介紹一下座標系。
主要有以下三種:
- WGS84:一種大地座標系,也是目前廣泛使用的GPS全球衛星定位系統使用的座標系。
- GCJ02:由中國國家測繪局制訂的地理信息系統的座標系統,是由WGS84座標系經過加密後的座標系。
- BD09:百度座標系,在GCJ02座標系基礎上再次加密。其中BD09LL表示百度經緯度座標,BD09MC表示百度墨卡托米制座標。
百度使用的自家BD09LL座標系,高德和騰訊都是GCJ02即火星座標系,所以相互之間是需要轉換的,不然會有位置偏移。
轉換方法:
/**
* BD-09 座標轉換成 GCJ-02 座標
*/
public static LatLng BD2GCJ(LatLng bd) {
double x = bd.longitude - 0.0065, y = bd.latitude - 0.006;
double z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * Math.PI);
double theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * Math.PI);
double lng = z * Math.cos(theta);
double lat = z * Math.sin(theta);
return new LatLng(lat, lng);
}
/**
* GCJ-02 座標轉換成 BD-09 座標
*/
public static LatLng GCJ2BD(LatLng bd) {
double x = bd.longitude, y = bd.latitude;
double z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * Math.PI);
double theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * Math.PI);
double tempLon = z * Math.cos(theta) + 0.0065;
double tempLat = z * Math.sin(theta) + 0.006;
return new LatLng(tempLat, tempLon);
}
業務需求
還是簡單描述一下業務需求,點擊一個地址或者按鈕或者地圖上的一個點,彈窗選擇第三方地圖導航,點擊選擇後調用第三方地圖進行導航。
1,點擊按鈕彈窗選擇
@OnClick({R.id.tv_navigation})
public void onViewClicked(View view) {
switch (view.getId()) {
...
case R.id.tv_navigation:
showMapList();
break;
}
}
2,彈窗
private void showMapList() {
final String[] mapNames = {"百度地圖", "高德地圖", "騰訊地圖"};
final String[] packageNames = {"com.baidu.BaiduMap", "com.autonavi.minimap", "com.tencent.map"};
AlertDialog.Builder builder = new AlertDialog.Builder(this)
.setTitle("請選擇地圖")
.setItems(mapNames, (dialogInterface, i) -> {
boolean installed = isInstalled(packageNames[i]);
if (installed) {
switch (i) {
case 0:
gotoBaiDuMap();
break;
case 1:
gotoGaoDeMap();
break;
case 2:
gotoTencentMap();
break;
}
} else {
ToastUtil.showCenterToast(mapNames[i] + "未安裝");
}
});
builder.create().show();
}
調用之前判斷一下是否安裝:
/**
* 檢測所選地圖是否安裝
*/
private boolean isInstalled(String packageName) {
PackageManager manager = this.getPackageManager();
List<PackageInfo> installedPackages = manager.getInstalledPackages(0);
if (installedPackages != null) {
for (PackageInfo info : installedPackages) {
if (info.packageName.equals(packageName))
return true;
}
}
return false;
}
3,調用地圖
別忘了 申請權限。
百度地圖
- 參數說明:
參數以字符串拼接的方式即可,這裏用StringBuffer拼接,比String易讀些。
- 調用示例:
private void gotoBaiDuMap() {
// 駕車導航
StringBuffer sb = new StringBuffer("baidumap://map/navi")
.append("?coord_type=gcj02")
.append("&query=").append("長寧圖書館")
.append("&src=").append(this.getPackageName());
Intent intent = new Intent();
intent.setData(Uri.parse(sb.toString()));
startActivity(intent);
}
高德地圖
- 參數說明:
- 調用示例:
private void gotoGaoDeMap() {
LatLng endPoint = BD2GCJ(new LatLng(31.220567, 121.395174));//轉換座標系
StringBuffer sb = new StringBuffer("androidamap://navi")
.append("?sourceApplication=").append(getString(R.string.app_name))
.append("&lat=").append(endPoint.latitude)
.append("&lon=").append(endPoint.longitude)
.append("&dev=0");
Intent intent = new Intent();
intent.addCategory(Intent.CATEGORY_DEFAULT);
intent.setPackage("com.autonavi.minimap");
intent.setData(Uri.parse(sb.toString()));
startActivity(intent);
}
騰訊地圖
- 參數說明:
- 調用示例:
private void gotoTencentMap() {
LatLng startPoint = BD2GCJ(new LatLng(mLatitude, mLongitude));//座標轉換
LatLng endPoint = BD2GCJ(new LatLng(31.220567, 121.395174));//座標轉換
StringBuffer sb = new StringBuffer("qqmap://map/routeplan")
.append("?type=drive")
.append("&from=我的位置")
.append("&fromcoord=").append(startPoint.latitude).append(",").append(startPoint.longitude)
.append("&to=長寧圖書館")
.append("&tocoord=").append(endPoint.latitude).append(",").append(endPoint.longitude)
.append("&referer=你的key");
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setData(Uri.parse(sb.toString()));
startActivity(intent);
}
注意,騰訊地圖這裏的from和to參數雖然可以省略,但是地圖上就不顯示地址了,默認是 地圖上的點,而且referer參數需要申請開發者key。
文檔
https://blog.csdn.net/Ever69/article/details/82427085