HarmonyOS鸿蒙Next中uniapp-BLE checkPermissionsCode is 401 at uni_modules/Ble-network/utssdk/app-harmony/index.uts:110
HarmonyOS鸿蒙Next中uniapp-BLE checkPermissionsCode is 401 at uni_modules/Ble-network/utssdk/app-harmony/index.uts:110 【问题描述】:uniapp开发工具,蓝牙ble问题,运行报错:uniapp-BLE checkPermissionsCode is 401 at uni_modules/Ble-network/utssdk/app-harmony/index.uts:110
【问题现象】:

【版本信息】:

【复现代码】:
// 导入模块
import abilityAccessCtrl, { Permissions, PermissionRequestResult } from '@ohos.abilityAccessCtrl'
import common from '@ohos.app.ability.common';
import { bundleManager } from '@kit.AbilityKit'
import { access, ble } from '@kit.ConnectivityKit';
import { BusinessError } from '@kit.BasicServicesKit';
// 常量定义
const TAG = "uniapp-BLE";
const permissions : Permissions[] = ['ohos.permission.ACCESS_BLUETOOTH'];
/**
* 设置蓝牙设备上报事件回调
*/
export function setDeviceFindListener(fn : () => void) {
if (typeof fn === 'function') {
ble.on("BLEDeviceFind", fn);
console.log("BLEDeviceFind", fn)
}
}
/**
* 开始蓝牙扫描
*/
export function startScan(filters : ble.ScanFilter[]) : void {
try {
ble.startBLEScan(filters);
} catch (err) {
console.error('errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message);
}
}
/**
* 停止蓝牙扫描
*/
export function stopScan() : void {
ble.stopBLEScan();
}
// 校验当前是否已经授权
async function checkAccessToken(permission : Permissions) : Promise<abilityAccessCtrl.GrantStatus> {
let atManager : abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager();
let grantStatus : abilityAccessCtrl.GrantStatus = abilityAccessCtrl.GrantStatus.PERMISSION_DENIED;
// 获取应用程序的accessTokenID
let tokenId : number = 0;
try {
let bundleInfo : bundleManager.BundleInfo =
await bundleManager.getBundleInfoForSelf(bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION);
let appInfo : bundleManager.ApplicationInfo = bundleInfo.appInfo
tokenId = appInfo.accessTokenId;
} catch (error) {
const err : BusinessError = error as BusinessError;
console.log(TAG, `Failed to get bundle info for self. Code is ${err.code}`);
}
// 校验应用是否被授予权限
try {
grantStatus = await atManager.checkAccessToken(tokenId, permission);
} catch (error) {
const err : BusinessError = error as BusinessError;
console.log(TAG, `Failed to check access token. Code is ${err.code}`);
}
return grantStatus
}
async function requestPermissionsFromUser() {
const context = getContext(); // 获取上下文
const atManager = abilityAccessCtrl.createAtManager();
try {
const result = await atManager.requestPermissionsFromUser(context, permissions);
if (result.code === 0) { // 请求权限成功
console.log('请求权限成功');
}
} catch (error) {
console.error('请求权限失败', error);
}
}
/**
* 检查权限
*/
export async function checkPermissions() : Promise<boolean> {
console.log(1111)
let result : boolean = false;
try {
console.log(2222)
let grantStatus : abilityAccessCtrl.GrantStatus = await checkAccessToken(permissions[0]);
if (grantStatus === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED) {
console.log('蓝牙权限已授予');
result = true;
} else {
console.log('蓝牙权限未授予');
return false;
}
return result;
} catch (error) {
const err : BusinessError = error as BusinessError;
console.log(TAG, 'checkPermissions' + `Code is ${err.code}`);
return result;
}
}
/**
* 申请蓝牙权限(处理首次申请/已拒绝场景)
* @returns boolean 权限是否授予
*/
async function requestBluetoothPermission(): Promise<boolean> {
if (!context) {
console.error(TAG, '上下文未初始化,请先调用setContext');
return false;
}
try {
// 第一步:申请权限(系统弹窗)
const requestResult = await abilityAccessCtrl.createAtManager().requestPermissionsFromUser(
context,
permissions
);
// 解析申请结果
const permissionItem = requestResult.authResults.find(item => item.permissionName === permissions[0]);
if (permissionItem?.grantStatus === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED) {
console.log('用户同意蓝牙权限');
return true;
}
// 第二步:用户拒绝后,检查是否为"不再询问"状态
const isNeverAskAgain = await checkNeverAskAgain(permissions[0]);
if (isNeverAskAgain) {
console.log('用户已拒绝并勾选不再询问,引导至设置页');
// 跳转到应用权限设置页(鸿蒙4.0+支持)
await openPermissionSettingPage();
return false;
} else {
console.log('用户临时拒绝权限');
return false;
}
} catch (error) {
const err: BusinessError = error as BusinessError;
console.log(TAG, `requestBluetoothPermission error: ${err.code}`);
return false;
}
}
async function openPermissionSettingPage() {
try {
// 获取当前应用包名
const bundleName = context.applicationInfo.bundleName;
// 跳转到系统设置的应用权限页面(鸿蒙4.0+ API)
await bundleManager.startAbility(
{
want: {
action: 'action.settings.APPLICATION_DETAILS_SETTINGS',
uri: `bundle://${bundleName}`,
},
context: context
}
);
} catch (error) {
console.error(TAG, '打开设置页失败:', error);
// 降级处理:提示用户手动打开设置
prompt.showToast({ message: '请前往设置>应用>本应用>权限中开启蓝牙权限' });
}
}
/**
* 向用户请求BLE权限
*/
export async function reqPermissionsFromUser() {
const context : common.UIAbilityContext = getContext() as common.UIAbilityContext;
let atManager : abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager();
atManager.requestPermissionsFromUser(context, permissions).then((data : PermissionRequestResult) => {
console.log('request Permissions success,请求权限成功');
}).catch((error : BusinessError) => {
console.log(TAG, `Failed to request permissions from user. Code is请求权限失败 ${error.code}`);
});
}
// 将函数挂载到对象后导出对象
export const myBLE = {
checkPermissions,
reqPermissionsFromUser,
setDeviceFindListener,
startScan,
stopScan
};
更多关于HarmonyOS鸿蒙Next中uniapp-BLE checkPermissionsCode is 401 at uni_modules/Ble-network/utssdk/app-harmony/index.uts:110的实战教程也可以访问 https://www.itying.com/category-93-b0.html
开发者你好,
可参考如下uni-app开发HarmonyOS应用,调用BLE。
【背景知识】
- uni-app的低功耗蓝牙相关接口暂时还没有支持HarmonyOS Next平台。
- uni-app可通过uts插件调用各平台系统能力,HarmonyOS Next平台uts开发指南。
【解决方案】
- 选中项目的uni_modules文件夹,右键新建uni_modules插件,选择uts插件-API插件,插件名称为:my-ble(名称可自定义)。
- 选中插件目录:
my-ble/utssdk,右键新建app-harmony目录,在app-harmony中新建uts文件。 - 在目录
my-ble/utssdk/app-harmony/index.uts中编写uts插件代码,以下为封装的调用低功耗蓝牙模块的uts插件代码示例。
// 导入模块
import abilityAccessCtrl, { Permissions, PermissionRequestResult } from '@ohos.abilityAccessCtrl'
import common from '@ohos.app.ability.common';
import { bundleManager } from '@kit.AbilityKit'
import { access, ble } from '@kit.ConnectivityKit';
import { BusinessError } from '@kit.BasicServicesKit';
// 常量定义
const TAG = "uniapp-BLE";
const permissions : Permissions[] = ['ohos.permission.ACCESS_BLUETOOTH'];
/**
* 设置蓝牙设备上报事件回调
*/
export function setDeviceFindListener(fn : () => void) {
if (typeof fn === 'function') {
ble.on("BLEDeviceFind", fn);
}
}
/**
* 开始蓝牙扫描
*/
export function startScan(filters : ble.ScanFilter[]) : void {
try {
ble.startBLEScan(filters);
} catch (err) {
console.error(`errCode: ${(err as BusinessError).code}, errMessage: ${(err as BusinessError).message}`);
}
}
/**
* 停止蓝牙扫描
*/
export function stopScan() : void {
ble.stopBLEScan();
}
// 校验当前是否已经授权
async function checkAccessToken(permission : Permissions) : Promise<abilityAccessCtrl.GrantStatus> {
let atManager : abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager();
let grantStatus : abilityAccessCtrl.GrantStatus = abilityAccessCtrl.GrantStatus.PERMISSION_DENIED;
// 获取应用程序的accessTokenID
let tokenId : number = 0;
try {
let bundleInfo : bundleManager.BundleInfo =
await bundleManager.getBundleInfoForSelf(bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION);
let appInfo : bundleManager.ApplicationInfo = bundleInfo.appInfo
tokenId = appInfo.accessTokenId;
} catch (error) {
const err : BusinessError = error as BusinessError;
console.error(TAG, `Failed to get bundle info for self. Code is ${err.code}`);
}
// 校验应用是否被授予权限
try {
grantStatus = await atManager.checkAccessToken(tokenId, permission);
} catch (error) {
const err : BusinessError = error as BusinessError;
console.error(TAG, `Failed to check access token. Code is ${err.code}`);
}
return grantStatus
}
/**
* 检查权限
*/
export async function checkPermissions() : Promise<boolean> {
let result : boolean = false;
try {
let grantStatus : abilityAccessCtrl.GrantStatus = await checkAccessToken(permissions[0]);
if (grantStatus === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED) {
result = true;
}
return result;
} catch (error) {
const err : BusinessError = error as BusinessError;
console.error(TAG, `checkPermissions Code is ${err.code}`);
return result;
}
}
/**
* 向用户请求BLE权限
*/
export async function reqPermissionsFromUser() {
const context : common.UIAbilityContext = getContext() as common.UIAbilityContext;
let atManager : abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager();
atManager.requestPermissionsFromUser(context, permissions).then((data : PermissionRequestResult) => {
console.info('request Permissions success');
}).catch((error : BusinessError) => {
console.error(TAG, `Failed to request permissions from user. Code is ${error.code}`);
});
}
// 将函数挂载到对象后导出对象
export const myBLE = {
checkPermissions,
reqPermissionsFromUser,
setDeviceFindListener,
startScan,
stopScan
};
- 在uni-app的vue文件中导入插件导出的myBLE对象,调用插件的方法使用系统蓝牙API,代码示例如下:
<template>
<view class="content">
<view class="btn-area">
<button @click="requestBlePermission" type="default">申请BLE蓝牙权限</button>
<button type="primary" @click="startBLEScan">使用BLE扫描设备</button>
<button type="warn" @click="stopBLEScan">停止BLE扫描</button>
<view v-if="devices.length > 0" class="device-list">
<view class="device-title">发现的设备:</view>
<view v-for="(device, index) in devices" :key="index" class="device-item" @click="connectToDevice(device)">
<text class="device-name">{{device.name || '未知设备'}} ({{device.deviceId}})</text>
<text class="device-rssi">RSSI: {{device.RSSI || '-'}}</text>
</view>
</view>
</view>
</view>
</template>
<script>
import {
myBLE,
} from "../../uni_modules/my-ble";
export default {
data() {
return {
devices: [],
isScanning: false
}
},
methods: {
// 请求蓝牙权限
async requestBlePermission() {
let hasPermission = await myBLE.checkPermissions();
if (!hasPermission) {
myBLE.reqPermissionsFromUser();
}
},
// 设置BLE回调
async startBLEScan() {
const hasPermission = await myBLE.checkPermissions()
if (hasPermission) {
// 设置发现蓝牙设备时的回调
myBLE.setDeviceFindListener((data) => {
data.forEach((item) => {
if (!this.devices.find(f => f.deviceId === item.deviceId)) {
this.devices.push(item);
}
});
})
// 设置过滤条件
let filters = null;
// 开始扫描
myBLE.startScan(filters);
}
},
stopBLEScan() {
myBLE.stopScan();
}
},
}
</script>
<style>
.content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding-bottom: 50px;
}
.logo {
height: 100rpx;
width: 100rpx;
margin-top: 100rpx;
margin-left: auto;
margin-right: auto;
margin-bottom: 25rpx;
}
.text-area {
display: flex;
justify-content: center;
margin-bottom: 20px;
}
.title {
font-size: 36rpx;
color: #8f8f94;
}
.btn-area {
width: 100%;
padding: 0 30px;
margin-top: 20px;
}
.btn-area button {
margin-bottom: 15px;
}
.result {
margin-top: 15px;
font-size: 14px;
color: #333;
text-align: center;
}
.device-list {
width: 100%;
margin-top: 15px;
margin-bottom: 15px;
border: 1px solid #eee;
border-radius: 5px;
padding: 10px;
}
.device-title {
font-size: 16px;
font-weight: bold;
padding-bottom: 5px;
border-bottom: 1px solid #eee;
margin-bottom: 5px;
}
.device-item {
padding: 10px;
border-bottom: 1px solid #f5f5f5;
display: flex;
flex-direction: column;
}
.device-item:active {
background-color: #f0f0f0;
}
.device-name {
font-size: 14px;
color: #333;
}
.device-rssi {
font-size: 12px;
color: #999;
margin-top: 5px;
}
</style>
更多关于HarmonyOS鸿蒙Next中uniapp-BLE checkPermissionsCode is 401 at uni_modules/Ble-network/utssdk/app-harmony/index.uts:110的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
老师,checkPermissions就是这个权限一些调不起来,不知道什么原因,能拉会给指导一下吗,
如何解决“此电脑”右键菜单中“显示更多选项”卡顿问题
问题描述
在 Windows 11 系统中,右键点击“此电脑”时,菜单会先显示“显示更多选项”,点击后才会出现完整菜单,这个过程有时会出现卡顿。
解决方法
方法一:修改注册表(推荐)
- 按
Win + R打开运行窗口,输入regedit并回车。 - 导航到以下路径:
HKEY_CURRENT_USER\Software\Classes\CLSID - 右键点击
CLSID,选择“新建” -> “项”,命名为:{86ca1aa0-34aa-4e8b-a509-50c905bae2a2} - 在新建的项下,再次右键选择“新建” -> “项”,命名为:
InprocServer32 - 完成后直接重启电脑,无需设置数值数据。
方法二:使用注册表脚本
- 新建一个文本文档,将以下内容复制进去:
Windows Registry Editor Version 5.00 [HKEY_CURRENT_USER\Software\Classes\CLSID\{86ca1aa0-34aa-4e8b-a509-50c905bae2a2}\InprocServer32] @="" - 将文件另存为
.reg格式(例如:fix_context_menu.reg)。 - 双击运行该文件,确认添加注册表信息。
- 重启电脑生效。
方法三:恢复默认设置
如果需要恢复 Windows 11 默认的右键菜单,请执行以下步骤:
- 新建一个文本文档,复制以下内容:
Windows Registry Editor Version 5.00 [-HKEY_CURRENT_USER\Software\Classes\CLSID\{86ca1aa0-34aa-4e8b-a509-50c905bae2a2}] - 将文件另存为
.reg格式(例如:restore_default.reg)。 - 双击运行该文件,确认删除注册表项。
- 重启电脑生效。
注意事项
- 修改注册表前建议先备份注册表或创建系统还原点。
- 操作完成后必须重启电脑才能使更改生效。
- 此方法适用于 Windows 11 系统,其他系统版本可能不适用。
最终开发者是权限未配置,问题解决,感谢,
检查在my-ble/utssdk/app-harmony/module.json5文件中,声明蓝牙权限。如下:
{
"module": {
"requestPermissions": [
{
// 蓝牙权限
"name": "ohos.permission.ACCESS_BLUETOOTH",
"reason": "$string:permission_ACCESS_BLUETOOTH",
"usedScene": {
}
},
]
}
}
在HarmonyOS Next中,uni-app的BLE模块返回401权限错误。该错误表示应用缺少蓝牙相关权限配置。需在AppScope/app.json5的module字段中,正确声明ohos.permission.USE_BLUETOOTH和ohos.permission.DISCOVER_BLUETOOTH权限。同时,确保在module.json5中请求了这些权限。权限配置完成后,需重新编译应用。
这个错误码401表示权限检查失败。从你的代码来看,checkAccessToken函数在获取accessTokenId时可能返回了0,导致后续权限检查失败。
问题出现在checkAccessToken函数中:
- 当获取
bundleInfo失败时,tokenId保持为初始值0 - 使用
tokenId=0调用checkAccessToken会返回401错误
建议修改checkAccessToken函数,在获取tokenId失败时直接返回拒绝状态:
async function checkAccessToken(permission: Permissions): Promise<abilityAccessCtrl.GrantStatus> {
let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager();
// 获取应用程序的accessTokenID
let tokenId: number = 0;
try {
let bundleInfo: bundleManager.BundleInfo =
await bundleManager.getBundleInfoForSelf(bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION);
let appInfo: bundleManager.ApplicationInfo = bundleInfo.appInfo
tokenId = appInfo.accessTokenId;
} catch (error) {
const err: BusinessError = error as BusinessError;
console.log(TAG, `Failed to get bundle info for self. Code is ${err.code}`);
// 获取tokenId失败,直接返回权限拒绝
return abilityAccessCtrl.GrantStatus.PERMISSION_DENIED;
}
// 如果tokenId为0,直接返回拒绝
if (tokenId === 0) {
console.log(TAG, 'Invalid tokenId (0)');
return abilityAccessCtrl.GrantStatus.PERMISSION_DENIED;
}
// 校验应用是否被授予权限
try {
return await atManager.checkAccessToken(tokenId, permission);
} catch (error) {
const err: BusinessError = error as BusinessError;
console.log(TAG, `Failed to check access token. Code is ${err.code}`);
return abilityAccessCtrl.GrantStatus.PERMISSION_DENIED;
}
}
另外,确保在调用蓝牙相关功能前,已经正确获取了上下文并申请了权限。错误码401通常表示参数无效,在这个场景下就是无效的tokenId。

