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,没什么难度,就不贴出来😝。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,029评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,395评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,570评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,535评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,650评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,850评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,006评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,747评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,207评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,536评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,683评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,342评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,964评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,772评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,004评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,401评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,566评论 2 349

推荐阅读更多精彩内容