一、前言

在微信小程序开发中,“获取用户当前定位”“拉起地图让用户选择位置”是非常高频的业务需求,比如外卖地址填写、线下门店打卡、商机现场定位等。

本文将基于 UniApp (Vue2) 框架,手把手教你如何实现这两个功能,并详细解答在基础库 2.17.0 之后,调用定位接口时经常遇到的 requiredPrivateInfos 权限报错问题。


二、功能实现:获取定位与地图选点

在 UniApp 中,官方为我们提供了两个非常便捷的 API:

  • uni.getLocation: 用于获取当前的地理位置(经纬度)。

  • uni.chooseLocation: 用于打开地图选择位置,并返回具体的地址名称和经纬度。

1. 完整示例代码

以下是一个可以直接运行的 Vue2 组件代码示例:

<template>
  <view class="location-container">
    <view class="info-box">
      <text class="label">当前位置:</text>
      <text class="content">{{ formData.locationText }}</text>
    </view>
    
    <view class="btn-group">
      <button type="primary" @click="getLocation">获取当前经纬度</button>
      <button type="default" @click="chooseLocation">打开地图选择位置</button>
    </view>
  </view>
</template>

<script>
export default {
  data() {
    return {
      formData: {
        latitude: '',    // 纬度
        longitude: '',   // 经度
        locationText: '暂未获取定位' // 页面显示的地址信息
      }
    };
  },
  methods: {
    // 1. 获取当前经纬度
    getLocation() {
      uni.showLoading({ title: '定位中...' });
      uni.getLocation({
        type: 'gcj02', // 默认为 wgs84 返回 gps 坐标,gcj02 返回可用于 uni.openLocation 的坐标
        success: (res) => {
          this.formData.latitude = res.latitude;
          this.formData.longitude = res.longitude;
          this.formData.locationText = `纬度: ${res.latitude.toFixed(6)} 经度: ${res.longitude.toFixed(6)}`;
          uni.hideLoading();
        },
        fail: (err) => {
          console.error('获取定位失败:', err);
          this.formData.locationText = '定位失败,请点击重新获取';
          uni.hideLoading();
          uni.showToast({ title: '获取定位失败', icon: 'none' });
        }
      });
    },

    // 2. 拉起地图选择位置
    chooseLocation() {
      uni.chooseLocation({
        success: (res) => {
          // res 包含:name(位置名称), address(详细地址), latitude, longitude
          this.formData.locationText = res.address || res.name || '已选择定位';
          this.formData.latitude = res.latitude;
          this.formData.longitude = res.longitude;
          console.log('选择的详细地址:', res);
        },
        fail: (err) => {
          console.error('选择位置取消或失败:', err);
          // 如果用户未选择地址或者取消了,且原本也没有位置信息,可以降级去获取当前位置
          if (!this.formData.locationText || this.formData.locationText === '暂未获取定位') {
            this.getLocation();
          }
        }
      });
    }
  }
};
</script>

<style scoped>
.location-container {
  padding: 30rpx;
}
.info-box {
  margin-bottom: 40rpx;
  padding: 20rpx;
  background-color: #f8f8f8;
  border-radius: 10rpx;
}
.btn-group button {
  margin-bottom: 20rpx;
}
</style>

三、踩坑警告:API 权限拦截报错排查

当你把上面的代码复制到项目中,满心欢喜地在微信开发者工具中点击按钮时,大概率会在控制台看到如下两条醒目的红色报错:

errMsg: "getLocation:fail the api need to be declared in the requiredPrivateInfos field in app.json/ext.json" errMsg: "chooseLocation:fail the api need to be declared in the requiredPrivateInfos field in app.json/ext.json"

为什么会报错?

这是因为微信小程序官方更新了用户隐私保护规则。如果小程序需要用到敏感 API(地理位置、相册、麦克风等),必须提前在配置文件中声明,并且向用户解释使用的原因。

完美解决三步曲:

第一步:修改 manifest.json 声明 API

由于我们使用的是 UniApp,不能直接修改原生的小程序 app.json。 请打开项目根目录下的 manifest.json,点击底部的 “源码视图”,找到 "mp-weixin" 节点,增加 requiredPrivateInfospermission 配置:

"mp-weixin" : {
    "appid" : "你的小程序AppID", 
    "setting" : {
        "urlCheck" : false
    },
    "usingComponents" : true,
    
    // 👇 1. 声明你使用到的隐私接口 👇
    "requiredPrivateInfos": [
        "getLocation",
        "chooseLocation"
    ],
    // 👇 2. 向用户解释获取位置的原因(弹窗时会显示给用户看) 👇
    "permission" : {
        "scope.userLocation" : {
            "desc" : "获取商机现场位置以便提供更准确的服务" // 务必根据真实业务填写
        }
    }
}
第二步:彻底重新编译

修改完 manifest.json 后,热更新大概率无效。必须在开发工具(如 HBuilderX)中停止运行,然后再重新启动微信开发者工具,让最新的配置项生效。

第三步:小程序后台配置隐私协议(极其关键,关系上线!)

很多新手改完了代码,发现开发者工具里能跑通了,结果一发体验版或者正式版,真机依然定位失败! 这是因为你没有在微信公众后台配置隐私声明。

  1. 登录 微信公众平台 (小程序后台)

  2. 左侧菜单栏:设置 -> 基本设置 -> 服务内容声明 -> 用户隐私保护指引

  3. 点击“更新”。

  4. 在信息收集列表中,添加 “位置信息”

  5. 填写的用途必须与你代码中 desc 的文案相呼应(比如:“用于获取商机现场位置”)。

  6. 提交审核。

完成以上步骤后,你的定位和地图选点功能就可以在全平台畅通无阻地运行了!


四、总结

在 UniApp 中开发小程序地图相关功能并不难,核心 API 只有 getLocationchooseLocation。但需要特别注意微信越来越严格的隐私合规要求。遇到 the api need to be declared... 报错时,记住“改 manifest 声明 + 更新后台隐私协议”这套组合拳即可轻松化解。

更多推荐