通过AbilityAccessCtrl动态向用户申请“允许不同设备间的数据交换”的权限,使用设备管理实例获取周边不可信设备列表。
说明: 查询周边不可信设备之前,请确保本设备与周边设备未进行配对。如果已配对,则恢复出厂设置之后重新查询。
相关概念
- 访问控制权限申请:应用的APL(Ability Privilege Level)等级分为normal、system_basic和system_core三个等级,默认情况下,应用的APL等级都为normal等级。权限类型分为system_grant和user_grant两种类型。应用可申请的权限项参见应用权限列表。
- 权限类型说明:根据授权方式的不同,权限类型可分为system_grant(系统授权)和user_grant(用户授权)。
- 应用ALP等级说明:元能力权限等级APL(Ability Privilege Level)指的是应用的权限申请优先级的定义,不同APL等级的应用能够申请的权限等级不同。
- 应用权限列表:在申请目标权限前,建议开发者先阅读访问控制开发概述-权限的工作流程。对权限的工作流程有基本的了解后,再结合以下权限的具体说明,判断应用能否申请目标权限,提高开发效率。
- 设备管理实例:用于获取可信设备和本地设备的相关信息。在调用DeviceManager的方法前,需要先通过createDeviceManager构建一个DeviceManager实例dmInstance。
约束与限制
通过DevEco Studio自动下载的SDK均为public版本,public-SDK不支持开发者使用系统API。本篇Codelab使用的DeviceManager(设备管理实例)依赖于系统API,需下载full-SDK并替换工具自动下载的public-SDK。具体操作可参考指南《如何替换full-SDK》。
相关权限
本篇Codelab需要在配置文件module.json5里添加允许不同设备间的数据交换权限:ohos.permission.DISTRIBUTED_DATASYNC。
环境搭建
软件要求
- DevEco Studio版本:DevEco Studio 3.1 Release。
- OpenHarmony SDK版本:API version 9。
硬件要求
- 开发板类型:润和RK3568开发板。
- OpenHarmony系统:3.2 Release。
环境搭建
完成本篇Codelab我们首先要完成开发环境的搭建,本示例以RK3568开发板为例,参照以下步骤进行:
-
获取OpenHarmony系统版本:标准系统解决方案(二进制)。以3.2 Release版本为例:
-
搭建烧录环境。
- 完成DevEco Device Tool的安装
- 完成RK3568开发板的烧录
-
搭建开发环境。
- 开始前请参考工具准备,完成DevEco Studio的安装和开发环境配置。
- 开发环境配置完成后,请参考使用工程向导创建工程(模板选择“Empty Ability”)。
- 工程创建完成后,选择使用真机进行调测。
代码结构解读
本篇Codelab只对核心代码进行讲解,对于完整代码,我们会在gitee中提供。
├──entry/src/main/ets // 代码区
│ ├──common
│ │ ├──constants
│ │ │ └──CommonConstants.ets // 公共常量类
│ │ └──util
│ │ ├──DeviceListUtil.ets // 设备查询工具类
│ │ ├──Logger.ets // 日志管理工具类
│ │ └──PermissionUtil.ets // 权限申请工具类
│ ├──entryability
│ │ └──EntryAbility.ts // 程序入口类
│ ├──pages
│ │ └──HomePage.ets // 主页面
│ └──view
│ ├──DeviceBean.ets // 设备信息类
│ ├──DeviceItem.ets // 设备信息对象
│ ├──DeviceListDialog.ets // 设备列表展示弹框
│ └──NoPermissionDialog.ets // 无权限弹框
└──entry/src/main/resource // 应用静态资源目录
页面设计
页面分为授权图片、授权说明、查询内网设备按钮三部分,效果如图所示:
// HomePage.ets
struct HomePage {
@State authorizedImage: Resource = $r('app.media.ic_unauthorized');
@State permissionDescribe: Resource = $r('app.string.no_permission');
noPermissionDialog: CustomDialogController = new CustomDialogController({
builder: NoPermissionDialog(),
autoCancel: false,
alignment: DialogAlignment.Bottom,
offset: {
dx: CommonConstants.DIALOG_OFFSET_X,
dy: CommonConstants.DIALOG_OFFSET_Y
}
});
deviceListDialog: CustomDialogController = new CustomDialogController({
builder: DeviceListDialog(),
autoCancel: false,
alignment: DialogAlignment.Bottom,
offset: {
dx: CommonConstants.DIALOG_OFFSET_X,
dy: CommonConstants.DIALOG_OFFSET_Y
}
})
...
build() {
Column() {
Image(this.authorizedImage)
...
Text(this.permissionDescribe)
...
Column() {
Button($r('app.string.button_text'), { type: ButtonType.Capsule, stateEffect: true })
...
}
...
}
...
}
}
授权状态为未授权时,点击查询内网设备按钮打开未申请权限提示的弹框,效果如图所示:
// NoPermissionDialog.ets
@CustomDialog
export struct NoPermissionDialog {
controller: CustomDialogController;
build() {
Column() {
Text($r('app.string.no_permission_title'))
...
Text($r('app.string.clear_permission'))
...
Text($r('app.string.dialog_confirm'))
...
.onClick(() => {
this.controller.close();
})
}
...
}
}
授权状态为已授权时,点击查询内网设备按钮打开设备查询列表弹框,效果如图所示:
// DeviceListDialog.ets
@CustomDialog
export struct DeviceListDialog {
private deviceListUtil: DeviceListUtil = new DeviceListUtil();
@State deviceList: Array<DeviceBean> = [];
controller: CustomDialogController;
...
build() {
Column() {
Text($r('app.string.device_list'))
...
Column() {
if (this.deviceList.length === 0) {
Text($r('app.string.no_device'))
...
} else {
Column() {
List() {
ForEach(this.deviceList, (item: DeviceBean, index: number) => {
ListItem() {
DeviceItem({item: item, index: index});
}
}, (item: DeviceBean) => JSON.stringify(item))
}
}
...
}
}
...
Text($r('app.string.dialog_confirm'))
...
.onClick(() => {
this.deviceListUtil.stopDeviceDiscovery();
this.controller.close();
})
}
...
}
}
权限申请
首次进入主页面弹出授权弹框,点击禁止按钮不会授权,点击允许按钮进行授权,再次进入首页不会出现授权弹框。
// HomePage.ets
struct HomePage {
...
async aboutToAppear() {
let result = await PermissionUtil.applyPermission();
if (result === 0) {
this.permissionDescribe = $r('app.string.has_permission');
this.authorizedImage = $r('app.media.ic_authorized');
} else {
this.permissionDescribe = $r('app.string.no_permission');
}
}
...
}
// PermissionUtil.ets
async applyPermission() {
let atManager = abilityAccessCtrl.createAtManager();
let data = await atManager.requestPermissionsFromUser(getContext(this), [CommonConstants.PERMISSION]);
let grantStatus: Array<number> = data.authResults;
let length: number = grantStatus.length;
if (length === 0) {
return 1;
}
return grantStatus[0];
}
主页面点击查询内网设备按钮时,先查询是否授权,根据授权状态打开对应的弹框(未授权:打开未授权弹框;已授权:打开设备查询列表弹框)。
// HomePage.ets
struct HomePage {
...
build() {
Column() {
...
Column() {
Button($r('app.string.button_text'), { type: ButtonType.Capsule, stateEffect: true })
...
.onClick(async () => {
let result = await PermissionUtil.checkPermission();
if(result === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED) {
this.deviceListDialog.open();
} else {
this.noPermissionDialog.open();
}
})
}
...
}
...
}
}
// PermissionUtil.ets
async checkPermission() {
let atManager = abilityAccessCtrl.createAtManager();
let grantStatus: abilityAccessCtrl.GrantStatus = abilityAccessCtrl.GrantStatus.PERMISSION_DENIED;
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 (err) {
Logger.error(TAG, 'getBundleInfoForSelf failed, code is ${err.code}, message is ${err.message}');
}
try {
grantStatus = await atManager.checkAccessToken(tokenId, CommonConstants.PERMISSION);
} catch (err) {
Logger.error(TAG, 'checkAccessToken failed, code is ${err.code}, message is ${err.message}');
}
return grantStatus;
}
设备查询
先创建dmInstance实例,再注册发现设备(deviceFoundOn)的回调方法,最后调用startDeviceDiscovery方法查询周边设备;当查询到设备之后调用deviceFoundOn方法处理设备信息。
//DeviceListDialog.ets
export struct DeviceListDialog {
...
aboutToAppear() {
this.deviceListUtil.initDmInstance((data: DeviceInfoInterface) => {
...
});
}
...
}
// DeviceListUtil.ets
// 创建dmInstance实例
initDmInstance(dealDeviceInfo: Function) {
this.dealDeviceInfo = dealDeviceInfo;
try {
deviceManager.createDeviceManager(getContext(this).applicationInfo.name, (err, data) => {
if (err) {
Logger.error(TAG, 'createDeviceManager errCode:' + err.code + ',errMessage:' + err.message);
return;
}
this.dmInstance = data;
this.deviceFoundOn();
this.startDeviceDiscovery();
});
} catch (err) {
Logger.error(TAG, 'createDeviceManager err=' + JSON.stringify(err));
}
}
// DeviceListUtil.ets
// 注册发现设备回调方法
deviceFoundOn() {
try {
if (this.dmInstance !== undefined) {
this.dmInstance.on('deviceFound', (data) => {
if (this.dealDeviceInfo !== undefined) {
this.dealDeviceInfo(data);
}
});
}
} catch (err) {
Logger.error(TAG, 'deviceFoundOn err:' + JSON.stringify(err));
}
}
// DeviceListUtil.ets
// 发现周边设备方法
startDeviceDiscovery() {
this.subscribeId = Math.floor(Math.random() * CommonConstants.RANDOM_ONE + CommonConstants.RANDOM_TWO);
let subscribeInfo: SubscribeInfoInterface = {
subscribeId: this.subscribeId,
mode: CommonConstants.MODE,
medium: 0,
freq: CommonConstants.FREQ,
isSameAccount: false,
isWakeRemote: true,
capability: 1
};
try {
if (this.dmInstance !== undefined) {
this.dmInstance.startDeviceDiscovery(subscribeInfo);
}
} catch (err) {
Logger.error(TAG, 'startDeviceDiscovery err:' + JSON.stringify(err));
}
}
最后
有很多小伙伴不知道学习哪些鸿蒙开发技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?而且学习时频繁踩坑,最终浪费大量时间。所以有一份实用的鸿蒙(HarmonyOS NEXT)资料用来跟着学习是非常有必要的。
这份鸿蒙(HarmonyOS NEXT)资料包含了鸿蒙开发必掌握的核心知识要点,内容包含了(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、Harmony南向开发、鸿蒙项目实战等等)鸿蒙(HarmonyOS NEXT)技术知识点。
希望这一份鸿蒙学习资料能够给大家带来帮助,有需要的小伙伴自行领取,限时开源,先到先得~无套路领取!!
如果你是一名有经验的资深Android移动开发、Java开发、前端开发、对鸿蒙感兴趣以及转行人员,可以直接领取这份资料
获取这份完整版高清学习路线,请点击→纯血版全套鸿蒙HarmonyOS学习资料
鸿蒙(HarmonyOS NEXT)最新学习路线
-
HarmonOS基础技能
-
HarmonOS就业必备技能
- HarmonOS多媒体技术
- 鸿蒙NaPi组件进阶
- HarmonOS高级技能
-
初识HarmonOS内核
- 实战就业级设备开发
有了路线图,怎么能没有学习资料呢,小编也准备了一份联合鸿蒙官方发布笔记整理收纳的一套系统性的鸿蒙(OpenHarmony )学习手册(共计1236页)与鸿蒙(OpenHarmony )开发入门教学视频,内容包含:ArkTS、ArkUI、Web开发、应用模型、资源分类…等知识点。
获取以上完整版高清学习路线,请点击→纯血版全套鸿蒙HarmonyOS学习资料
《鸿蒙 (OpenHarmony)开发入门教学视频》
《鸿蒙生态应用开发V2.0白皮书》
《鸿蒙 (OpenHarmony)开发基础到实战手册》
OpenHarmony北向、南向开发环境搭建
《鸿蒙开发基础》
- ArkTS语言
- 安装DevEco Studio
- 运用你的第一个ArkTS应用
- ArkUI声明式UI开发
- .……
《鸿蒙开发进阶》
- Stage模型入门
- 网络管理
- 数据管理
- 电话服务
- 分布式应用开发
- 通知与窗口管理
- 多媒体技术
- 安全技能
- 任务管理
- WebGL
- 国际化开发
- 应用测试
- DFX面向未来设计
- 鸿蒙系统移植和裁剪定制
- ……
《鸿蒙进阶实战》
- ArkTS实践
- UIAbility应用
- 网络案例
- ……
获取以上完整鸿蒙HarmonyOS学习资料,请点击→纯血版全套鸿蒙HarmonyOS学习资料
总结
总的来说,华为鸿蒙不再兼容安卓,对中年程序员来说是一个挑战,也是一个机会。只有积极应对变化,不断学习和提升自己,他们才能在这个变革的时代中立于不败之地。 文章来源:https://www.toymoban.com/news/detail-856475.html
文章来源地址https://www.toymoban.com/news/detail-856475.html
到了这里,关于OpenHarmony开发实战:为应用添加运行时权限(ArkTS)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!