uni.getLocation()和uni.openSetting()

发布于:2025-05-22 ⋅ 阅读:(16) ⋅ 点赞:(0)

环境

  • Windows 11 专业版
  • HBuilder X 4.65
  • 微信开发者工具 Stable 1.06.2412050

背景

在小程序开发中,需要用户授权地址位置信息,以获取当前的经纬度,从而进一步获取省市等地理信息。

可通过两种方法来让用户授权:

  • uni.getLocation()
  • uni.openSetting()

前者界面如下:

在这里插入图片描述

后者界面如下:

在这里插入图片描述

关于二者的区别和联系,后面会有详细介绍。

问题

在调用 uni.getLocation() 时,并没有弹出对话框,而是报错了:

"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.jsonrequiredPrivateInfos 字段中声明才能调用,否则会报错。

对于UniApp项目,则需要修改 manifest.json 文件。

在该文件的 "mp-weixin" 下面,添加 requiredPrivateInfos 信息如下:

    "mp-weixin" : {
    ......
        "requiredPrivateInfos": ["getLocation"],
        "permission" : {
            "scope.userLocation" : {
                "desc" : "你的位置信息将用于小程序位置接口的效果展示"
            }
        }
    },
    ......

注:这里的 desc ,就是弹出对话框时的描述信息。

完整代码如下:

// 获取地理位置
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() 有两个回调方法,分别对应 seccessfail 。缺少 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

网站公告

今日签到

点亮在社区的每一天
去签到