- 技术栈:React、Taro、TS
在微信小程序中,打开摄像头、麦克风,获取地理位置等接口,都需要经过授权才能调用,详见微信官方文档。
既然每次都需要授权,那我每次使用前调用一次 wx.authorize
不就得了?
js
Taro.authorize({
scope: 'scope.camera',
success: (res) => {
// 用户已经同意小程序使用摄像头功能,可以进行下一步操作了(如调用扫码)
// Taro.scanCode()
},
fail: (err) => {
// 拒绝授权了
},
第一次调用时,出现了令人激动的绿色弹框!
手抖点了拒绝,尝试再次点击(调用wx.authorize
时),发现没反应了???
仔细阅读了官方文档,发现了这句话
如果用户之前已经同意授权,则不会出现弹窗,直接返回成功。
那么如果之前拒绝授权呢?没说,但实操发现也不会出现弹框。
寻找思路:
官方文档的示例中,wx.getSetting
和wx.authorize
搭配使用,其作用是查询授权信息。
把wx.getSetting
调用成功返回的信息打印出来
发现authSetting中记录了用户授权结果,刚才拒绝了授权,所以scope.camera是false
那么,可以得到上次授权结果了,需要做的是在上次拒绝之后还能重新询问授权。wx.openSetting
)可以满足这一需求
调起客户端小程序设置界面,返回用户设置的操作结果。设置界面只会出现小程序已经向用户请求过的权限。
梳理一下整个流程
进一步调试wx.openSetting
,总结出其与操作流程的对应关系
wx.getSetting查看的权限情况 | 说明 | 所需操作 |
---|---|---|
res.authSetting['scope.record']===true | 之前询问过这个权限,并且用户已经同意了 | 已经有这个权限了,调用api即可 |
res.authSetting['scope.record']===false | 之前询问过这个权限,但是用户拒绝了 | 需要跳到小程序的设置界面(openSetting) |
res.authSetting['scope.record']不存在 | 还没有询问过这个权限 | 用wx.authorize这个api询问用户获取权限 |
(注:这里借用了一个大佬的思路,但是文章链接现在找不到了)
打开小程序的设置页面需要用户主动主动点击触发,所以这里加一个modal,用户点击确定时调用openSetting
上代码
可以封装为异步函数便于使用
js
import Taro from "@tarojs/taro"
/**
*
* @param {*} scopeStr // 'scope.record' // 权限列表 https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/authorize.html
* @returns
*/
export const checkPermisson = (scopeStr) => {
return new Promise((resolve, reject) => {
Taro.getSetting({
success: async (res) => {
const authSettingObj = res.authSetting
if (authSettingObj[scopeStr] === true) {
// 当前已经有权限了
return resolve()
} else if (authSettingObj[scopeStr] === false) {
// 之前问过权限,但是拒绝了
try {
await openSetting(scopeStr)
return resolve()
} catch {
return reject()
}
} else {
// 还没问过权限
// 去请求授权
Taro.authorize({
scope: scopeStr,
success: (res) => {
return resolve()
},
fail: async (err) => {
// 拒绝授权了
// 打开setting
try {
await openSetting(scopeStr)
return resolve()
} catch {
return reject()
}
},
})
}
},
})
})
}
// 打开设置权限的页面 去设置权限 通过showModal去触发点击
export const openSetting = (scopeStr) => {
return new Promise((resolve, reject) => {
Taro.showModal({
title: '温馨提示',
content: '请授权微信小程序相关权限,以使用更多功能',
success: (res) => {
if (res.confirm) {
Taro.openSetting({
success: function (res) {
console.log('打开权限设置页面', res)
const authSettingObj = res.authSetting
if (scopeStr) {
// 有指定去获取的权限
if (authSettingObj[scopeStr] === true) {
return resolve()
} else {
return reject()
}
} else {
// 没有指定去获取的权限
return resolve()
}
},
})
} else {
return reject()
}
},
fail: (err) => {
return reject()
},
})
})
}
使用示例:
js
onScan = async () => {
try {
await checkPermisson('scope.camera');
Taro.scanCode({
scanType: ['qrCode'],
success: (res) => {
console.log(res);
},
fail: (res) => {}
})
} catch (e) {
console.log(e, '获取权限失败');
}
}
其他问题
在使用getLocation获取地址时报错 {"errMsg":"getLocation:fail the api need to be declared in the requiredPrivateInfos field in app.json/ext.json"}
报错信息很明确,需要在app.json加requiredPrivateInfos
解决方法:在app.config.ts加入
js
permission: {
"scope.userLocation": {
"desc": "你的位置信息将用于小程序位置接口的坐标展示"
}
},
requiredPrivateInfos: [
"getLocation"
],
微信官方文档提到:
自 2022 年 7 月 14 日后发布的小程序,使用以下8个地理位置相关接口时,需要声明该字段,否则将无法正常使用。2022 年 7 月 14 日前发布的小程序不受影响。
...
注:若使用以上接口,均需在小程序管理后台,「开发」-「开发管理」-「接口设置」中自助开通该接口权限。