文章目录
环境
- Windows 11 专业版
- HBuilder X 4.65
- 微信开发者工具 Stable 1.06.2412050
背景
在小程序开发中,需要用户授权地址位置信息,以获取当前的经纬度,从而进一步获取省市等地理信息。
可通过两种方法来让用户授权:
uni.getLocation()
uni.openSetting()
前者界面如下:

后者界面如下:

关于二者的区别和联系,后面会有详细介绍。
问题
在调用 uni.getLocation()
时,并没有弹出对话框,而是报错了:
powershell
"getLocation:fail the api need to be declared in the requiredPrivateInfos field in app.json/ext.json"
然后在调用 uni.openSetting()
时,在设置页面里,也并没有"位置消息",只有"订阅消息":

分析
这其实是两个问题。
问题1
调用 uni.getLocation()
时报错。
这个错误是因为微信小程序要求从2022年起,部分敏感接口(如 getLocation
)必须在 app.json
/ ext.json
的 requiredPrivateInfos
字段中声明才能调用,否则会报错。
对于UniApp项目,则需要修改 manifest.json
文件。
在该文件的 "mp-weixin"
下面,添加 requiredPrivateInfos
信息如下:
javascript
"mp-weixin" : {
......
"requiredPrivateInfos": ["getLocation"],
"permission" : {
"scope.userLocation" : {
"desc" : "你的位置信息将用于小程序位置接口的效果展示"
}
}
},
......
注:这里的 desc
,就是弹出对话框时的描述信息。
完整代码如下:
javascript
// 获取地理位置
uni.getLocation({
type: 'wgs84',
success: (res) => {
console.log("位置获取成功:", res.latitude, res.longitude);
},
fail: (err) => {
console.error("获取位置失败:", err);
if (err.errMsg.includes("permission")) {
// 引导用户授权
uni.showModal({
title: '权限提示',
content: '需要地理位置权限才能继续',
success: (modalRes) => {
if (modalRes.confirm) {
uni.openSetting(); // 跳转设置页
}
}
});
}
}
});
问题2
调用 uni.openSetting()
时没有"位置消息"。
这是因为,微信小程序的设置页默认只显示已申请过的权限。比如说,用户之前拒绝过地理位置权限,那么设置页就会显示该选项。
那么问题来了,前面不是明明已经调用了 uni.getLocation()
,为什么还说没有申请过权限呢?原因很简单,因为调用 uni.getLocation()
报错了,并没有成功。
因此,把问题1解决后,问题2就迎刃而解了。
uni.getLocation()和uni.openSetting()的区别和联系
从前面的代码中我们看到,先是调用 uni.getLocation()
,如果fail了,就再调用 uni.openSetting()
,这是为什么呢?两者不都是授权吗?既然 uni.getLocation()
已经被用户拒绝了,为什么还要通过 uni.openSetting()
让用户手工设置呢?
这主要是因为小程序有一个"静默期"机制,目的是防止开发者频繁骚扰用户。如果第一次调用 uni.getLocation()
时,用户选择了拒绝,后面再调用时就不再弹框了。
具体说来,当用户第一次调用 uni.getLocation()
时,系统会弹窗询问权限,用户可以选择允许或者拒绝。
- 允许:则下次调用
uni.getLocation()
时,不再弹窗,直接获取用户地理位置信息。 - 拒绝:同理,下次调用
uni.getLocation()
时,不再弹窗,直接失败(静默期通常持续几分钟到几小时,具体由微信控制)
在静默期,唯一能让用户重新开启权限的方式就是,引导用户主动进入设置页(openSetting)手动开启权限:
- 设置页是用户主动操作进入的(非自动弹窗),不受静默期限制
- 用户可能误点拒绝,需要提供明确的修正入口
当然,用户在静默期也可以直接去手机的权限设置里去设置权限,不过通过引导用户主动进入设置页,显然对于用户来说会有更好的体验。
此外,从前面代码中可见,是先调用 uni.showModal()
弹出对话框,如果用户选择"确定",才调用 uni.openSetting()
跳转设置页。也就是说,对于敏感权限,必须用户显式触发,才能去设置。这里可能不能直接设置,不过我没有验证过。
其它
uni.getLocation()的fail
uni.getLocation()
有两个回调方法,分别对应 seccess
和 fail
。缺少 requiredPrivateInfos
报错,以及点击"拒绝"按钮,都会触发 fail
回调,但是二者的error不一样:
- 缺少
requiredPrivateInfos
:"getLocation:fail the api need to be declared in the requiredPrivateInfos field in app.json/ext.json"
- 点击"拒绝"按钮:
"getLocation:fail auth deny"
必要时,可通过error内容来判断fail的原因。
uni.openSetting()的authSetting对象
在从 uni.openSetting()
获取用户配置的位置消息时,其 success
回调包含了response参数,该参数包含了 authSetting
对象。通过该对象的 scope.userLocation
属性来判断用户对位置消息的设置值,其中true表示允许,false表示不允许:

但要注意,如果页面上没有位置消息的设置,则authSetting里也就不包含 scope.userLocation
属性。如果尝试获取,则获取到的是 undefined
。
参考
https://uniapp.dcloud.net.cn/api/location/location.html#getlocation
https://uniapp.dcloud.net.cn/api/other/setting.html#opensetting