Android項目中調起手機地圖導航

現在,移動應用中集成地圖已經成爲一種趨勢。導航 - 作爲地圖中不可或缺的一項功能,被很多移動應用所青睞,然而,導航方式選擇上,爲了減少不必要的資源和apk容量,一般應用都選擇通過調用第三方的地圖應用來實現導航功能。在介紹之前,先看一下最終效果:
未安裝狀態截圖

未安裝地圖應用
  本文主要提供幾種常用的調起三方地圖應用的導航平臺,以高德,百度,騰訊,谷歌地圖爲例。

地圖平臺 Uri文檔
高德地圖 http://lbs.amap.com/api/uri-api/guide/travel/route
百度地圖 http://lbsyun.baidu.com/index.php?title=uri/api/android
谷歌地圖 https://developers.google.com/maps/documentation/android-api/intents
騰訊地圖 http://lbs.qq.com/uri_v1/guide-route.html

  各大地圖服務商基本都提供了Uri,方便其他應用調用(除了騰訊),uri網址如上所示.

基本看了以上的文檔就會使用了,下面就提供幾個平臺的基本寫法吧:

  • 高德地圖導航:

      高德地圖較爲特殊,其他地圖平臺都可以選擇傳入地址或者經緯度作爲參數,而高德要求必須有經緯度。沒辦法,那就先擼個地理編碼的輪子吧,方便我們將地址信息轉化爲準確的經緯度座標,具體看下面代碼:

/**
     * by moos on 2017/09/18
     * func:調用高德地圖的地理編碼接口,返回經緯度座標
     * @param address
     */
    private void translateAddressToLocation(String address){


        OkHttpUtils
                .get()
                .url(GEOCODE_HTTP_URL + "address="+address+"&key="+SELF_AMAP_KEY)
                .build()
                .execute(new StringCallback() {
                    @Override
                    public void onError(Call call, Exception e, int id) {
                        Log.e("地理編碼失敗=", e.getMessage());
                        //DialogUtils.dismissProgressDialog();
                        Toast.makeText(UnityScanActivity.this, getString(R.string.act_qr_code_fail), Toast.LENGTH_LONG).show();
                    }
                    @Override
                    public void onResponse(String response, int id) {

                        Logger.e("地理編碼結果 =" + response);
                        resultBean = JSONObject.parseObject(response, GeocodeResultBean.class);
                        if (resultBean.getStatus().equals("1")) {

                            locationList = resultBean.getGeocodes();
                            if(locationList!=null && locationList.size()>0){
                                //默認獲取第一條
                                locationString = locationList.get(0).getLocation();
                                lon = locationString.substring(0,locationString.indexOf(","));
                                lat = locationString.substring(locationString.indexOf(",")+1,locationString.length());
                                Log.e("經緯度信息爲===",lon+"======="+lat);
                            }else {
                                Toast.makeText(UnityScanActivity.this, "無相關信息", Toast.LENGTH_LONG).show();
                            }


                        } else {
                            Toast.makeText(UnityScanActivity.this, resultBean.getInfo(), Toast.LENGTH_LONG).show();
                        }

                    }
                });

    }

  這裏我並沒有採用高德包中的地理編碼接口來實現,而是調用的其web接口。請原諒我的任性,最近接口調上癮了��,值得注意的是,url中需要傳入key,這個要在高德官網自己創建web應用申請,不過很方便,不需要包名和sha1等。

下面看看如何調起手機中的高德地圖吧:

//調起導航的uri
    private final String BAIDU_MAP_NAVI_URI = "baidumap://map/navi?query=";
    private final String GAODE_MAP_NAVI_URI = "androidamap://navi?sourceApplication=";
    private final String GOOGLE_MAP_NAVI_URI = "google.navigation:q=";
    //map app包名
    private final String BAIDU_MAP_APP = "com.baidu.BaiduMap";
    private final String GAODE_MAP_APP = "com.autonavi.minimap";
    private final String GOOGLE_MAP_APP = "com.google.android.apps.maps";

    private final String QQ_MAP_URL = "http://apis.map.qq.com/uri/v1/routeplan?type=drive&";
    //高德web服務的臨時key(用於地理編碼)
    private final String SELF_AMAP_KEY = "your key";
    private final String GEOCODE_HTTP_URL = "http://restapi.amap.com/v3/geocode/geo?";
    private GeocodeResultBean resultBean;
    private List<GeocodeResultBean.GeocodeBean> locationList;
    private String locationString;
    private String lon;
    private String lat;
/**
     * by moos on 2017/09/18
     * func:調起高德導航
     * @param lat 緯度
     * @param lon 經度
     * @param dev 是否偏移(0:lat 和 lon 是已經加密後的,不需要國測加密; 1:需要國測加密)
     * @param style 導航方式(0 速度快; 1 費用少; 2 路程短; 3 不走高速;4 躲避擁堵;5 不走高速且避免收費;6 不走高速且躲避擁堵;7 躲避收費和擁堵;8 不走高速躲避收費和擁堵)
     */
    private void goNaviByGaoDeMap(String lat,String lon,String dev,String style){

        Intent intent = new Intent();
        intent.setAction(Intent.ACTION_VIEW);
        intent.addCategory(Intent.CATEGORY_DEFAULT);
        //將功能Scheme以URI的方式傳入data
        Uri uri = Uri.parse(GAODE_MAP_NAVI_URI +
                 "Test"
               + "&lat=" + lat
               + "&lon=" + lon
               + "&dev=" + dev
               + "&style=" +style);
        intent.setData(uri);
        intent.setPackage("com.autonavi.minimap");
        startActivity(intent);
    }

註釋比較詳細了,就不做具體講解了,可以參考官方提供的文檔。

  • 百度地圖導航:
/**
     * by moos on 2017/09/18
     * func:調起百度導航
     */
    private void goNaviByBaiDuMap(String address){

        Intent intent = new Intent();
        intent.setData(Uri.parse(BAIDU_MAP_NAVI_URI + address));
        startActivity(intent);

    }
  • 谷歌地圖導航:
/**
     * by moos on 2017/09/18
     * func:調起谷歌導航
     * @param lat
     * @param lon
     */
    private void goNaviByGoogleMap(String lat,String lon,String address){

        Uri uri = Uri.parse(GOOGLE_MAP_NAVI_URI+lat+","+lon +"," + address);
        Intent mapIntent = new Intent(Intent.ACTION_VIEW, uri);
        mapIntent.setPackage("com.google.android.apps.maps");
        context.startActivity(mapIntent);
    }
  • 騰訊地圖導航:
      剛剛說過,騰訊地圖目前還未支持其他應用以uri形式調起騰訊自家的地圖功能,不過我們可以通過web 接口方式調用,具體代碼如下,比較簡單:
/**
     * by moos on 2017/09/18
     * func:通過網頁形式調起騰訊地圖
     * @param startPoint
     * @param endPoint
     * @param policy 規劃策略(0:快捷,1:無高速,2:距離短)
     * @param appName 當前應用的名稱
     */
    private void goNaviByTencentMap(String startPoint,String endPoint,String policy,String appName){

        Uri uri = Uri.parse(QQ_MAP_URL + "from="+startPoint + "&to=" +endPoint + "&policy="+policy + "&referer="+appName );
        Intent intent = new Intent(Intent.ACTION_VIEW,uri);
        startActivity(intent);
    }

我們只需要在url中傳入參數,然後訪問該網址就可以,很簡單吧��。

  • 其他:
      爲了更好的用戶體驗,我們會加上一些提醒用戶的交互,如:用戶手機沒有安裝地圖應用,可以彈窗讓用戶前往商店下載,來吧,一大波代碼來襲:
/**
     * by moos on 2017/09/18
     * func:接受導航請求,併發起導航
     */
    private void navigateForDestination(){
        if(isApplicationInstall(GAODE_MAP_APP)){
            //安裝了高德map
            Log.e("Tminstore","已安裝高德地圖");
            translateAddressToLocation("東方明珠");//地理編碼
            goNaviByGaoDeMap(lat,lon,"1","2");
            //goNaviByTencentMap(MyApplication.mapLocation.getAddress(),"上海東方明珠","0","com.ucardstore.Activity");

        }else if(isApplicationInstall(BAIDU_MAP_APP)){
            //安裝了百度map
            Log.e("Tminstore","已安裝百度地圖");
            goNaviByBaiDuMap("上海東方明珠");

        }else if(isApplicationInstall(GOOGLE_MAP_APP)){
            //安裝了google map
            Log.e("Tminstore","已安裝谷歌地圖");
            goNaviByGoogleMap("","","上海東方明珠");

        }else {

            //默認安裝高德app
            showInstallAppTip();

            //使用騰訊網頁地圖(可選)
            //goNaviByTencentMap(MyApplication.mapLocation.getAddress(),"上海東方明珠","0","com.ucardstore.Activity");
        }
    }

    .....

    /**
     * by moos on 2017/09/18
     * func:判斷手機是否安裝了該應用
     * @param packageName
     * @return
     */
    private boolean isApplicationInstall(String packageName){
        return new File("/data/data/" + packageName).exists();
    }

    ......

    /**
     * by moos on 2017/09/18
     * func:安裝地圖app的提示
     */
    private void showInstallAppTip(){
        TipDialog dialog = new TipDialog(this, new View.OnClickListener() {

            @Override
            public void onClick(View arg0) {
                switch (arg0.getId()) {
                    case R.id.dialog_btn_sure:

                        Intent intent ;
                        Uri uri = Uri.parse("market://details?id=com.autonavi.minimap");
                        intent = new Intent(Intent.ACTION_VIEW, uri);
                        startActivity(intent);

                        break;
                    case R.id.dialog_btn_cancel:

                        break;
                }
            }
        });


        dialog.setMessage(getString(R.string.install_app_tip));
        dialog.setBtnSure(getString(R.string.go_to_install));
        dialog.setBtnCancel(getString(R.string.cancel));
        dialog.show();
    }

  好了,這差不多就是全部代碼了,至於彈窗TipDialog是我自定義的dialog,沒什麼難度,就不貼出來��。
  最後,打一波廣告,歡迎大家下載新潮的AR定製應用Tminstore來體驗,也歡迎大家反饋問題��。
Tminstore , 一款AR定製應用

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