23_微信小程序蓝牙-权限适配篇
注: 示例代码使用uniapp编写,下面通过uni.
调用的API侧重于微信侧,等同于wx.
,
微信小程序中使用蓝牙模块,首先必须要调用uni.openBluetoothAdapter
初始化蓝牙模块。只有蓝牙模块初始化成功,后续的蓝牙相关API才能调用成功,而uni.openBluetoothAdapter
受限于小程序的授权管理机制,以及微信app
的授权管理机制。
一.微信小程序使用蓝牙的权限适配
当微信小程序首次调用uni.openBluetoothAdapter
,会弹出弹窗提示用户允许
或拒绝
,如果用户点击允许,那么这个权限授权成功,如果用户点了拒绝,那么下一次调用uni.openBluetoothAdapter
,是不会有弹窗提示的,并且uni.openBluetoothAdapter
调用结果返回失败。
uni.openBluetoothAdapter().catch((err) => {
uni.showModal({
content: JSON.stringify(err)
})
return Promise.reject()
}).then((res) => {
uni.showModal({
content: "蓝牙模块初始化成功"
})
})
这种情况,在调用uni.openBluetoothAdapter
之前,使用uni.authorize({scope: "scope.bluetooth"})
预先授权,当首次弹出授权弹窗,用户点击了拒绝后,uni.authorize({scope: "scope.bluetooth"})
返回失败结果,此时可以使用uni.getSetting
判断用户是否授权,如果没有授权,使用uni.openSetting
,打开小程序设置页,引导用户授权。
<template>
<view class="index__test-btn" @click="toOpenBluetoothAdapter($event)">openBluetoothAdapter</view>
</template>
<script>
export default {
methods: {
toOpenBluetoothAdapter: function() {
const openBluetoothAdapter = () => {
return uni.openBluetoothAdapter().catch((err) => {
uni.showModal({
content: `openBluetoothAdapter: ${JSON.stringify(err)}`
})
return Promise.reject()
})
}
this.authorizeBluetooth().catch((err) => {
uni.showModal({
content: `authorizeBluetooth: ${JSON.stringify(err)}`
})
return Promise.reject()
}).then((res) => {
return openBluetoothAdapter()
}).then((res) => {
uni.showModal({
content: "蓝牙模块初始化成功"
})
})
},
authorizeBluetooth: function() {
const scope = "scope.bluetooth"
const openSetting = () => {
return uni.showModal({
content: "您需要在设置中开启\"蓝牙\"选项,才可以使用蓝牙哦!",
cancelText: "任性不去",
confirmText: "去设置",
}).then((res) => {
if (res.confirm) {
return uni.openSetting().catch((error) => {
console.log("openSetting", error)
return Promise.reject({
"errMsg": "openSetting:fail system error",
"errno": -2
})
}).then((res) => {
let authSetting = res.authSetting || {}
if (authSetting[scope]) {
return Promise.resolve()
} else {
return openSetting()
}
})
} else {
return Promise.reject({
"errMsg": "authorize:fail auth deny",
"errno": 103
})
}
})
}
const getSetting = () => {
return uni.getSetting().catch((error) => {
return Promise.reject({
"errMsg": "authorize:fail system error",
"errno": -2
})
}).then((res) => {
let authSetting = res.authSetting || {}
let keys = Object.keys(authSetting)
if (keys.indexOf(scope) != -1) {
if(!authSetting[scope]) {
return openSetting()
} else {
return Promise.resolve()
}
} else {
return Promise.reject({
"errMsg": "authorize:fail auth canceled",
"errno": -3
})
}
})
}
return uni.authorize({scope: scope}).catch((err) => {
return getSetting()
})
}
}
}
</script>
当我们允许小程序使用蓝牙授权后,调用uni.openBluetoothAdapter
后,又报了system permission denied
二.微信app使用蓝牙的权限适配
调用uni.openBluetoothAdapter
后,之所以会报system permission denied
这个错,是因为:
- 安卓 6.0 及以上版本手机,无
定位权限
或定位开关
未打开 - 安卓 12 及以上版本手机,无
搜索附件设备权限
或附件设备
开关未打开 - iOS手机,未打开
微信app访问蓝牙的开关
这几种情况,只能用户手动去手机的系统设置里面授权。
如果上述权限都已经授权的情况下,系统的蓝牙开关未开启,uni.openBluetoothAdapter
也无法被成功调用。
针对上述权限的适配,以及用户未打开系统蓝牙开关的情况,目前只能是写一个使用说明,把授权流程写清楚,引导用户按照流程操作。
<script>
/**
* 蓝牙权限待申请
*/
const BLUETOOTH_AUTHOR_PENDING = "BLUETOOTH_AUTHOR_PENDING"
/**
* 蓝牙权限被拒绝
*/
const BLUETOOTH_AUTHOR_REJECT = "BLUETOOTH_AUTHOR_REJECT"
/**
* BluetoothAdapter不可用
*/
const BLUETOOTH_ADAPTER_UNAVAILABLE = "BLUETOOTH_ADAPTER_UNAVAILABLE"
/**
* 蓝牙适配器可用
*/
const BLUETOOTH_ADAPTER_AVAILABLE = "BLUETOOTH_ADAPTER_AVAILABLE"
export default {
data() {
return {
bluetoothStatus: BLUETOOTH_AUTHOR_PENDING
}
},
onLoad() {
},
methods: {
toOpenBluetoothAdapter: function() {
const openBluetoothAdapter = () => {
return uni.openBluetoothAdapter().catch((err) => {
this.bluetoothStatus = BLUETOOTH_ADAPTER_UNAVAILABLE
return Promise.reject()
})
}
this.bluetoothStatus = BLUETOOTH_AUTHOR_PENDING
this.authorizeBluetooth().then((res) => {
return openBluetoothAdapter()
}).catch((err) => {
uni.showModal({
content: "蓝牙模块初始化失败",
confirmText: "如何解决"
}).then((res) => {
if(res && res.confirm) {
if(this.bluetoothStatus == BLUETOOTH_AUTHOR_REJECT) {
this.toOpenBluetoothAdapter()
} else {
uni.navigateTo({
url: `/pages/bluetooth-solution-page/bluetooth-solution-page`
})
}
}
})
return Promise.reject()
}).then((res) => {
this.bluetoothStatus = BLUETOOTH_ADAPTER_AVAILABLE
uni.showModal({
content: "蓝牙模块初始化成功"
})
})
},
authorizeBluetooth: function() {
const scope = "scope.bluetooth"
const openSetting = () => {
return uni.showModal({
content: "您需要在设置中开启\"蓝牙\"选项,才可以使用蓝牙哦!",
cancelText: "任性不去",
confirmText: "去设置",
}).then((res) => {
if (res.confirm) {
return uni.openSetting().catch((error) => {
console.log("openSetting", error)
return Promise.reject({
"errMsg": "openSetting:fail system error",
"errno": -2
})
}).then((res) => {
let authSetting = res.authSetting || {}
if (authSetting[scope]) {
return Promise.resolve()
} else {
return openSetting()
}
})
} else {
return Promise.reject({
"errMsg": "authorize:fail auth deny",
"errno": 103
})
}
})
}
const getSetting = () => {
return uni.getSetting().catch((error) => {
return Promise.reject({
"errMsg": "authorize:fail system error",
"errno": -2
})
}).then((res) => {
let authSetting = res.authSetting || {}
let keys = Object.keys(authSetting)
if (keys.indexOf(scope) != -1) {
if(!authSetting[scope]) {
return openSetting()
} else {
return Promise.resolve()
}
} else {
return Promise.reject({
"errMsg": "authorize:fail auth canceled",
"errno": -3
})
}
})
}
return uni.authorize({scope: scope}).catch((err) => {
return getSetting()
}).catch((err) => {
this.bluetoothStatus = BLUETOOTH_AUTHOR_REJECT
return Promise.reject(err)
})
}
}
}
</script>
三.蓝牙权限引导页
/pages/bluetooth-solution-page/bluetooth-solution-page
页面内容如下:

