熟悉的朋友知道我最近一段时间在搞安卓方面的内容,使用uni-app开发的这段时间总算是体会到了网上兄弟们的心声。
怎么说呢?难以言喻!
想要无能狂怒的叱骂,却又不得不默默的翻看API文档一点点的摸索,找到解决之路的那一刻,不亚于我买双色球中五块钱大奖的那天心情。
最近需要用uni-app实现一下定位的问题,其实就是获取经纬度,然后通过 MQTT 发送到服务器上。(关于MQTT部分详见上文 # uni-app实现本地MQTT连接)
接到这个需求的时候感觉非常简单,因为 uni-app 本身就有定位的API。
js
uni.getLocation({
type: 'wgs84',
success: function (res) {
console.log('当前位置的经度:' + res.longitude);
console.log('当前位置的纬度:' + res.latitude);
}
});
一段代码搞定问题,但是,项目那边突然传来消息说:定位不到。
我这边使用 Trae 紧急排查,但是却没发现任何问题,Trae 也表示系统运行非常稳定。
但是项目现场就是反馈定位不到,一下午的时间 Trae 建议我排查了设备本身、安卓版本、代码语法、打包过程等等。经过一下午的排查终于确定了原因是"没联网"。
气得我当场怒骂...
现在需求确定清楚了:离线定位。
这里需要注意一点,虽然设备不接入网络,但事实定位本身是依赖于接收卫星信号。也就是说,没网可以,但是设备必须有GPS定位模块,否则是无法实现定位的。
首先在 manifest.json 文件中找到 modules,在下面添加 Geolocation 启用定位模块。
同时在 distribute / android / permissions 权限部分增加定位权限部分。
还需要在 SDK 配置部分增加定位内容。
js
"modules" : {
"Geolocation" : {} // 启用定位模块
},
/* 应用发布信息 */
"distribute" : {
/* android打包配置 */
"android" : {
"permissions" : [
...
"<uses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_COARSE_LOCATION\"/>"
]
},
},
/* SDK配置 */
"sdkConfigs" : {
"geolocation" : {
"system" : {
"__platform__" : [ "android" ]
}
}
}
我在网上找到的方案是仍然使用 uni-app 的 getLocation 方法,将请求方式改为 gcj02 的方式。
js
uni.getLocation({
type: 'gcj02',
success: function (res) {
console.log('当前位置的经度:' + res.longitude);
console.log('当前位置的纬度:' + res.latitude);
}
});
但是不知道为什么在我这个终端上这个写法并没有获取到定位信息,甚至代码都不走,多方排查也没有发现问题出在哪儿,遂放弃此方案。
在 Trae 的建议下改为使用 html+ 的定位方案。
js
testGetLocation() {
let that = this;
// #ifdef APP-PLUS
plus.geolocation.getCurrentPosition(
(position) => {
console.log('【定位成功】', position);
that.location = {
latitude: position.coords.latitude,
longitude: position.coords.longitude
};
},
(error) => {
console.log('【定位失败】', error);
let msg = '定位失败';
switch (error.code) {
case 1:
msg = '用户拒绝定位授权';
break;
case 2:
msg = 'GPS 功能未开启';
break;
case 3:
msg = '响应超时';
break;
default:
msg = '未知错误';
}
}, {
provider: 'gps', // 强制使用 GPS 定位
timeout: 30000, // 最大30秒超时
highAccuracy: true, // 启用高精度模式
maximumAge: 0 // 不使用缓存位置
}
);
// #endif
},
采用这个方案成功获取到了定位信息,但是需要注意两个点:
- 必须获得用户授权,尤其是在高版本安卓系统中。(本人采用的是安卓11及以下的设备)
- 设备尽量在户外使用(GPS定位在室内很容易定位不到)
授权部分可以参考如下方法:
js
getLocationSafely(onSuccess, onError) {
let that = this;
plus.geolocation.getCurrentPosition(
() => {},
(e) => {
if (e.code === 4) {
// 位置服务未开启
uni.showModal({
title: '定位服务未开启',
content: '请前往系统设置开启位置信息,才能获取当前位置',
showCancel: true,
confirmText: '去设置',
success: (res) => {
if (res.confirm) {
// 跳转到系统设置
plus.runtime.openURL('package:com.android.settings');
}
}
});
onError?.(new Error('系统定位未开启'));
return;
}
}, {
// 3秒超时
timeout: 3000
}
);
},
还需要注意的一个点是如果采用自定义基座 ,一定要记得将定位模块云打包到基座中,否则也是无法定位的。