一篇关于移动端应用打开手机地图应用进行导航的文章(uniapp开发,多场景适配,浙里办及非浙里办环境的实现)

1,447 阅读3分钟

一个已经上架了很久的浙里办应用,用户突然让在有市场名称的地方加点击跳转到手机地图App导航的功能

646d2c2182eabe97360165fa9a28039e.jpeg
作为敬业的乙方,当然马(bu)上(xiang)动工实现乙方的需求。

浙里办环境下

环境准备

浙里办上架的应用可以同时在浙里办App、浙里办微信小程序以及浙里办支付宝小程序三个环境下使用,所以要将三种情况都考虑到。
1、浙里办App环境
在index.html文件里引入

<script type="text/javascript" src="//assets.zjzwfw.gov.cn/assets/ZWJSBridge/1.1.0/zwjsbridge.js"></script>

2、浙里办微信小程序环境
需要借助weixin-js-sdk和uuid,可以直接通过包管理工具下载,在使用的地方引入。uuid用来获取设备的唯一标识

npm install weixin-js-sdk
npm install uuid
import wx from 'weixin-js-sdk';
import {v4 as uuid} from 'uuid' // 使用ECMAScript 模块语法引入有可能会报错,报错就是用下面的CommonJS 语法引入即可
// 或者
const {v4: uuid} = require('uuid')

*在页面加载的时候写入以下配置

// 跳转地图app相关配置
wx.config({
    debug: false,
    appId: '应用的appid,可以在IRS应用发布系统上查找,或直接使用微信小程序的appid',
    timestamp: new Date().getTime(),
    nonceStr: uuid().toString().replace(/-/g, ''),
    signature: '应用的appkey,同样可以在IRS应用发布系统上找到',
    jsApiList: ['openLocation'],
});	

此配置一定要填写正确,不然功能不会实现

3、浙里办支付宝小程序 在index.html文件里引入

<script src="https://gw.alipayobjects.com/as/g/h5-lib/alipayjsapi/3.1.1/alipayjsapi.min.js"></script>

功能实现源代码

直接上代码

import wx from 'weixin-js-sdk'
const {ZWJSBridge, ap} = window

const openMapApp = (dataObj) => {
// 用来判断当前环境
const bIsWeixinMini = window.navigator.userAgent.toLowerCase().includes('miniprogram/wx') || window.__wxjs_environment === 'miniprogram' 
    const sUserAgent = window.navigator.userAgent.toLowerCase();
    const bIsDtDreamApp = sUserAgent.indexOf('dtdreamweb') > -1; 
    if (bIsDtDreamApp) {// 浙里办APP环境
      if(dataObj.longitude && dataObj.latitude){
        const openUrl = `zwfw://openThirdMap?longitude=${dataObj.longitude}&latitude=${dataObj.latitude}&locationName=${dataObj.name}`;
        ZWJSBridge.openLink({
          url: openUrl,
        }).then((result) => {
          console.log(result);
        }).catch((error) => {
          console.log(error);
        });
      }else{
        Toast.show({
          content: '获取当前位置失败,请重试',
        });
      }
    } else if(bIsWeixinMini){ // 浙里办微信小程序环境
      wx.ready(() => {
            wx.openLocation({
              longitude: parseFloat(dataObj.longitude),
              latitude: parseFloat(dataObj.latitude),
              name: dataObj.name,
              address: dataObj.address,
            });
      })
    } else{ // 浙里办支付宝小程序
        window.ap.openLocation({
            longitude: dataObj.longitude,
            latitude: dataObj.latitude,
            name: dataObj.name,
            address: dataObj.address,
        });
    }
};

module.exports = {
    openMapApp: openMapApp
}

非浙里办环境下功能的实现

我解决了包括微信小程序、App以及h5三种环境下的实现,以及Android和ios差异性的解决。上源码
注:h5端实现此功能需要借助callapp-lib
下载使用

npm install callapp-lib  
import CallApp from 'callapp-lib';
openMapApp () {
    //#ifdef MP
    // 只适用于微信小程序
    uni.openLocation({
        longitude: parseFloat(this.mtkData.market.longitude),
        latitude: parseFloat(this.mtkData.market.latitude),
        name: this.mtkData.market.name,
        address: this.mtkData.market.address,
        scale: 18,
        success: res => {
                console.log(res)
        }
    })
    //#endif

    //#ifdef APP-PLUS
    let latitude = this.mtkData.market.latitude
    let longitude = this.mtkData.market.longitude
    let name = this.mtkData.market.name
    let url = "";
    if (plus.os.name == "Android") {//判断是安卓端
        plus.nativeUI.actionSheet({//选择菜单
            title: "选择应用",
            cancel: "取消",
            buttons: [{title: "腾讯地图"},{title: "百度地图"}, {title: "高德地图"}]
        }, function(e) {
            switch (e.index) {
                    //下面是拼接url,不同系统以及不同地图都有不同的拼接字段
                case 1:
                        //注意referer=xxx的xxx替换成你在腾讯地图开发平台申请的key
                        url = `qqmap://map/geocoder?coord=${latitude},${longitude}&referer=xxx`;
                        break;
                case 2:
                        url = `baidumap://map/marker?location=${latitude},${longitude}&title=${name}&coord_type=gcj02&src=andr.baidu.openAPIdemo`;
                        break;
                case 3:
                        url = `androidamap://viewMap?sourceApplication=appname&poiname=${name}&lat=${latitude}&lon=${longitude}&dev=0`;
                        break;
                default:
                        break;
            }
            if (url != "") {
                url = encodeURI(url);
                //plus.runtime.openURL(url,function(e){})调起手机APP应用
                plus.runtime.openURL(url, function(e) {
                        plus.nativeUI.alert("本机未安装指定的地图应用");
                });
            }
        })
    } else {
        // iOS上获取本机是否安装了百度高德地图,需要在manifest里配置
        // 在manifest.json文件app-plus->distribute->apple->urlschemewhitelist节点下添加
        //(如urlschemewhitelist:["iosamap","baidumap"])  
        plus.nativeUI.actionSheet({
                title: "选择地图应用",
                cancel: "取消",
                buttons: [{title: "腾讯地图"},{title: "百度地图"}, {title: "高德地图"}]
        }, function(e) {
            switch (e.index) {
                case 1:
                    url = `qqmap://map/geocoder?coord=${latitude},${longitude}&referer=xxx`;
                    break;
                case 2:
                    url = `baidumap://map/marker?location=${latitude},${longitude}&title=${name}&content=${name}&src=ios.baidu.openAPIdemo&coord_type=gcj02`;
                    break;
                case 3:
                    url = `iosamap://viewMap?sourceApplication=applicationName&poiname=${name}&lat=${latitude}&lon=${longitude}&dev=0`;
                    break;
                default:
                    break;
            }
            if (url != "") {
                url = encodeURI(url);
                plus.runtime.openURL(url, function(e) {
                    plus.nativeUI.alert("本机未安装指定的地图应用");
                });
            }
        })
    }
    //#endif


    //#ifdef H5
    // 此处打开了一个自定义的popup,通过点击popup的按钮执行h5OpenApp方法
    this.$refs.popup1.open()
    //#endif
},
//h5打开手机导航app
h5OpenApp (index) {
    let _this = this
    let name = this.mtkData.market.name
    let lat1 = this.mtkData.market.latitude
    let lon1 = this.mtkData.market.longitude
    let system = navigator.userAgent
    let isAndroid = system.indexOf('Android') > -1 || system.indexOf('Linux') > -1; //android终端或者uc浏览器
    let isiOS = !!system.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); //ios终端
    console.log('系统', isAndroid, isiOS)
    if (index === 1) { //打开高德地图
        let scheme1 = ''
        if (isAndroid) {
            scheme1 = 'androidamap'
        } else if (isiOS) {
            scheme1 = 'iosamap'
        }
        const options = {
            scheme: {
              protocol: scheme1
            },
            intent: {
              package: '',
              scheme: ''
            },
            // appstore: '填写appstore的下载地址',
            // yingyongbao: '填写应用宝的下载地址',
            // fallback: '填写唤端失败后跳转的地址。'
            logFunc: (status) => {
                _this.$refs.popup1.close()
                console.log(status, 'status')
                if (status === 'failure') {
                    uni.showModal({
                            title: '提示',
                            content: '打开失败,请确定高德地图是否已下载。'
                    })
                }
            }
        }
        const callLib = new CallApp(options)

        callLib.open({
            // param: `sourceApplication=appname&poiname=衢州新农都&&lat=${lat1}&lon=${lon1}dev=0`,
            param: {
                sourceApplication: 'appname',
                poiname: this.mtkData.market.name,
                lat: lat1,
                lon: lon1,
                dev: 0
            },
            path: 'viewMap'
        })
    } else if (index === 2) { //打开百度地图
        if (isAndroid) {
            const options = {
                scheme: {
                  protocol: 'baidumap'
                },
                intent: {
                  package: '',
                  scheme: ''
                },
                // appstore: '填写appstore的下载地址',
                // yingyongbao: '填写应用宝的下载地址',
                // fallback: '填写唤端失败后跳转的地址。'
                logFunc: (status) => {
                    _this.$refs.popup1.close()
                    console.log(status, 'status')
                    if (status === 'failure') {
                            uni.showModal({
                                    title: '提示',
                                    content: '打开失败,请确定百度地图是否已下载。'
                            })
                    }
                }
            }
            const callLib = new CallApp(options)

            callLib.open({
                // param: `sourceApplication=appname&poiname=衢州新农都&&lat=${lat1}&lon=${lon1}dev=0`,
                param: {
                    location: lat1 + ',' + lon1,
                    title: name,
                    coord_type: 'gcj02',
                    src: 'andr.baidu.openAPIdemo'
                },
                path: 'map/marker',
                callback: res => {
                }
            })
        } else if (isiOS) {
            const options = {
                scheme: {
                  protocol: 'baidumap'
                },
                intent: {
                  package: '',
                  scheme: ''
                },
                // appstore: '填写appstore的下载地址',
                // yingyongbao: '填写应用宝的下载地址',
                // fallback: '填写唤端失败后跳转的地址。'
                logFunc: (status) => {
                    _this.$refs.popup1.close()
                    console.log(status, 'status')
                    if (status === 'failure') {
                        uni.showModal({
                            title: '提示',
                            content: '打开失败,请确定百度地图是否已下载。'
                        })
                    }
                }
            }
            const callLib = new CallApp(options)

            callLib.open({
                // param: `sourceApplication=appname&poiname=衢州新农都&&lat=${lat1}&lon=${lon1}dev=0`,
                param: {
                    location: lat1 + ',' + lon1,
                    title: name,
                    content: name,
                    coord_type: 'gcj02',
                    src: 'ios.baidu.openAPIdemo'
                },
                path: 'map/marker',
                callback: res => {
                    console.log(res)
                }
            })
        }
    }
},

补充:更为便捷的方式

通过点击跳转到地图服务的浏览器web网页,网页会提醒下载或跳转到对应的地图App。

// 高德地图
window.open(`https://uri.amap.com/marker?position=${lon1},${lat1}&name=${name}&coordinate=gaode&callnative=1`)

// 百度地图
window.open(`http://api.map.baidu.com/marker?location=${lat1},${lon1}&title=${name}&content=${name}&output=html&src=webapp.baidu.openAPIdemo`)

// 腾讯地图
window.open(`https://3gimg.qq.com/lightmap/v1/marker/?marker=coord:${lat1},${lon1};title:${name};addr:${name}&referer=在腾讯位置服务平台申请的应用的名称&key=在腾讯位置服务平台申请的应用的key`)