uniapp 调用第三方地图导航

在 uniapp 中调用第三方地图导航,主要用 URL Scheme。

基本思路

通过 plus.runtime.openURL() 打开地图应用的 URL Scheme,传入目标经纬度,应用会自动打开并导航。

常用地图的 URL Scheme

高德地图

  • iOS: iosamap://path?dname=目的地&dlat=纬度&dlon=经度&dev=0&t=0
  • Android: androidamap://route?dname=目的地&dlat=纬度&dlon=经度&dev=0&t=0

百度地图

  • 通用: baidumap://map/direction?destination=latlng:纬度,经度|name:目的地&mode=driving

腾讯地图

  • 通用: qqmap://map/routeplan?type=drive&to=目的地&tocoord=纬度,经度

苹果地图(仅 iOS)

  • maps://maps.apple.com/?daddr=纬度,经度&dirflg=d

检测应用是否安装

使用 plus.runtime.isApplicationExist() 检测:

1
2
3
4
5
// Android 用包名,iOS 用 Scheme
const isInstalled = plus.runtime.isApplicationExist({
pname: 'com.autonavi.minimap', // Android 包名
action: 'iosamap://' // iOS Scheme
});

注意:iOS 9+ 需要在 manifest.json 的 plus.distribute.apple.urlschemewhitelist 中添加 Scheme 白名单,否则无法检测。

实现流程

  1. 获取目标经纬度
  2. 检测已安装的地图应用
  3. 弹出选择列表让用户选择
  4. 根据选择打开对应的 URL Scheme

注意事项

基本就是这样,实现起来不难,主要是整理好各个地图的 URL 格式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
/**
* 地图导航工具函数
* 支持高德地图、百度地图、腾讯地图、苹果地图、谷歌地图
*/

/**
* 获取系统信息
*/
function getSystemInfo() {
return new Promise((resolve) => {
uni.getSystemInfo({
success: (res) => {
resolve(res);
},
fail: () => {
resolve({});
}
});
});
}

/**
* 检测应用是否安装
* @param {String} pname - Android平台的应用包名
* @param {String} action - iOS平台的应用Scheme
* @returns {Boolean}
*/
function checkAppInstalled(pname, action) {
try {
return plus.runtime.isApplicationExist({
pname: pname || '',
action: action || ''
});
} catch (error) {
console.error('检测应用安装失败:', error);
return false;
}
}

/**
* 获取所有可能的地图应用列表(不检测是否安装)
* @param {Number} latitude - 纬度
* @param {Number} longitude - 经度
* @param {String} name - 地点名称(可选)
* @returns {Promise<Array>}
*/
async function getAllMaps(latitude, longitude, name = '') {
const systemInfo = await getSystemInfo();
const platform = systemInfo.platform || '';
const isIOS = platform === 'ios';
const isAndroid = platform === 'android';

const maps = [];

// 高德地图
// Android包名: com.autonavi.minimap
// iOS Scheme: iosamap://
maps.push({
name: '高德地图',
pname: 'com.autonavi.minimap', // Android包名
action: 'iosamap://', // iOS Scheme
scheme: isIOS ? 'iosamap://' : 'androidamap://',
url: isIOS
? `iosamap://path?sourceApplication=applicationName&dname=${encodeURIComponent(name || '目的地')}&dlat=${latitude}&dlon=${longitude}&dev=0&t=0`
: `androidamap://route?sourceApplication=amap&dname=${encodeURIComponent(name || '目的地')}&dlat=${latitude}&dlon=${longitude}&dev=0&t=0`
});

// 百度地图
// Android包名: com.baidu.BaiduMap
// iOS Scheme: baidumap://
maps.push({
name: '百度地图',
pname: 'com.baidu.BaiduMap', // Android包名
action: 'baidumap://', // iOS Scheme
scheme: 'baidumap://',
url: `baidumap://map/direction?origin=我的位置&destination=latlng:${latitude},${longitude}|name:${encodeURIComponent(name || '目的地')}&mode=driving&coord_type=gcj02`
});

// 腾讯地图
// Android包名: com.tencent.map
// iOS Scheme: qqmap://
maps.push({
name: '腾讯地图',
pname: 'com.tencent.map', // Android包名
action: 'qqmap://', // iOS Scheme
scheme: 'qqmap://',
url: `qqmap://map/routeplan?type=drive&from=我的位置&to=${encodeURIComponent(name || '目的地')}&tocoord=${latitude},${longitude}`
});

// 苹果地图(仅iOS)
if (isIOS) {
maps.push({
name: '苹果地图',
pname: '', // iOS不需要包名
action: 'maps://', // iOS Scheme
scheme: 'maps://',
url: `maps://maps.apple.com/?daddr=${latitude},${longitude}&dirflg=d`
});
}

// 谷歌地图(主要Android)
if (isAndroid) {
maps.push({
name: '谷歌地图',
pname: 'com.google.android.apps.maps', // Android包名
action: 'google.navigation:', // Android也可以使用
scheme: 'google.navigation:',
url: `google.navigation:q=${latitude},${longitude}`
});
}

return maps;
}

/**
* 获取已安装的地图应用列表
* @param {Number} latitude - 纬度
* @param {Number} longitude - 经度
* @param {String} name - 地点名称(可选)
* @returns {Promise<Array>}
*/
async function getAvailableMaps(latitude, longitude, name = '') {
const allMaps = await getAllMaps(latitude, longitude, name);
const installedMaps = [];

// 检测每个地图应用是否已安装
for (const map of allMaps) {
const isInstalled = checkAppInstalled(map.pname, map.action);
if (isInstalled) {
installedMaps.push(map);
}
}

return installedMaps;
}

/**
* 打开地图应用
* @param {String} url - 地图应用的URL
* @param {String} mapName - 地图应用名称
*/
function openMapApp(url, mapName) {
plus.runtime.openURL(url, (error) => {
if (error) {
uni.showToast({
title: `未安装${mapName}`,
icon: 'none'
});
}
});
}

/**
* 显示地图选择列表并跳转
* @param {Number} latitude - 纬度
* @param {Number} longitude - 经度
* @param {String} name - 地点名称(可选)
* @param {Object} options - 配置选项
* @param {String} options.title - 选择列表标题
* @param {String} options.cancelText - 取消按钮文字
*/
export async function openNavigation(latitude, longitude, name = '', options = {}) {
if (!latitude || !longitude) {
uni.showToast({
title: '经纬度不能为空',
icon: 'none'
});
return;
}

try {
const maps = await getAvailableMaps(latitude, longitude, name);

if (maps.length === 0) {
uni.showModal({
title: '提示',
content: '请安装地图应用(高德地图、百度地图、腾讯地图等)',
showCancel: false,
confirmText: '知道了'
});
return;
}

const itemList = maps.map(map => map.name);

uni.showActionSheet({
title: options.title || '选择地图应用',
itemList: itemList,
cancelText: options.cancelText || '取消',
success: (res) => {
const selectedMap = maps[res.tapIndex];
openMapApp(selectedMap.url, selectedMap.name);
},
fail: (err) => {
// 用户取消选择
if (err.errMsg !== 'showActionSheet:cancel') {
console.error('显示地图选择失败:', err);
}
}
});
} catch (error) {
console.error('打开导航失败:', error);
uni.showToast({
title: '打开导航失败',
icon: 'none'
});
}
}