文章目录
- 基于OpenHarmony提供的分布式能力,实现在同一个网络下拉起远程设备的Ability,本节主要分享分布式中最基础的能力,分布式拉起的实现。
-
- 系统版本:OpenHarmony 3.1 release SDK:OpenHarmony API 8 设备:Hi3516 IDE:DevEco Studio 3.0 Beta3 PC:win10 64
- 1、在Hi3616开发板上烧写OpenHarmony 3.1 release系统。 2、准备两台烧录相同的版本系统的Hi3516DV300开发板A,B。 3、两个开发板A,B配置在同一个WiFi网络之下。打开设置–>WLAN–>点击右侧WiFi开关–>点击目标WiFi并输入密钥。
- 以下内容是本地学习和整理的材料,如果有不对的地方请留言指正,谢谢。
- 1、用户授权,分布式启动远程FA需要申请敏感权限:ohos.permission.DISTRIBUTED_DATASYNC,用户授权成功后才可以使用。 2、通过deviceManager.createDeviceManager()创建设备管理对象实例DeviceManager。 3、同步获取所有可信设备列表:deviceManager.getTrustedDeviceListSync()。 4、启动发现设备:deviceManager.startDeviceDiscovery()。 5、注册监听器:deviceManager.on()。 deviceStateChange:设备状态发生改变,比如上班上线、下线、状态同步完成。 deviceFound:发现设备。 discoverFail:发现设备失败。 serviceDie:服务停止。 6、设备认证:deviceManager.authenticateDevice(),两台设备互联需要先建立认证,认证通过两台设备即为可信设备,可以进行一些分布式操作。 7、启动远端FA,featureAbility.startAbility(),其中featureAbility是@ohos.ability.featureAbility。
-
- 说明:需要申请的权限可以在config.json的module模块中进行声明。 module{"reqPermissions": [ { "name": "ohos.permission.DISTRIBUTED_DATASYNC" } ]}
- 说明:敏感权限需要用户授权后才可以访问,本案例应用启动就需要申请,所以在index.js的onInit()方法中申请。
- AbilityContext.requestPermissionsFromUser(permissions: Array<string>, requestCallback: AsyncCallback<PermissionRequestResult>) : void;
- 参数:PermissionRequestResult。 说明:权限请求结果。 备注:本模块首批接口从API 9开始支持。后续版本的新增接口,采用上角标单独标记接口的起始版本。
- grantPermission() { let context = featureAbility.getContext(); context.requestPermissionsFromUser(REQUEST_PERMISSION_LIST, REQUEST_PERMISSION_CODE, function(result){ console.log('request Permissions From User Result:' + JSON.stringify(result)); // todo 判断是否授权 } } 获取DeviceManager实例: 说明:需要操作设备必须获取设备实例才可以=,ohos.distributedHardware.deviceManager中提供了创建的方法:createDeviceManager(bundleName: string, callback: AsyncCallback): void。 备注:DeviceManager API
- registerDeviceListCallback(callback) { if (typeof (this.#deviceManager) === 'undefined') { // 获取设备管理对象 let self = this; deviceManager.createDeviceManager('com.nlas.myapplication', (error, value) => { if (error) { console.error('createDeviceManager failed.'); return; } self.#deviceManager = value;// 设备管理器对象实例 // 执行操作... }) } else { // 设备管理器对象已经存在,直接可以执行操作... } }
- 说明:同步获取所有可信设备列表 deviceManager.getTrustedDeviceListSync(): Array。
- // 同步获取所有可信设备列表var list = this.#deviceManager.getTrustedDeviceListSync();console.info('[RemoteDeviceModel] deviceList=' + JSON.stringify(list));
- 接口:deviceManager.startDeviceDiscovery(subscribeInfo: SubscribeInfo):void。
- 参数:SubscribeInfo。
- // 随机数SUBSCRIBE_ID = Math.floor(65536 * Math.random());var info = { subscribeId: SUBSCRIBE_ID,// 服务订阅ID【0~65535】,对每个发现进程来说应该是唯一的 mode: 0xAA,//主动模式 medium: 2,//订阅媒介 2-wifi freq: 2,// 订阅频率 高 isSameAccount: false,// 只能找到帐号相同的设备 isWakeRemote: true,// 发现休眠设备 capability: 0 };console.info('[RemoteDeviceModel] startDeviceDiscovery ' + SUBSCRIBE_ID);deviceManager.startDeviceDiscovery(info);// 发现设备
- 注册设备状态回调。 关键字:deviceStateChange。 接口:deviceManager.on(type: ‘deviceStateChange’, callback: Callback<{ action: DeviceStateChangeAction, device: DeviceInfo }>): void。
- 参数:DeviceStateChangeAction。 说明:表示设备状态变化的枚举。 参数:DeviceInfo。 说明:设备信息。 参数:DeviceType。 说明:表示设备类型的枚举类。
- deviceManager.on(DEVICE_STATE_CHANGE, (data) => { console.info('[RemoteDeviceModel] deviceStateChange data=' + JSON.stringify(data)); if (data == null) { return; } switch (data.action) { case 0: { self.deviceList[self.deviceList.length] = data.device; console.info('[RemoteDeviceModel] online, updated device list=' + JSON.stringify(self.deviceList)); self.callback(); if (self.authCallback != null) { self.authCallback(); self.authCallback = null; } break; } case 1: { if (self.deviceList.length > 0) { for (var i = 0; i < self.deviceList.length; i++) { if (self.deviceList[i].deviceId === data.device.deviceId) { self.deviceList[i] = data.device; break; } } } console.info('[RemoteDeviceModel] change, updated device list=' + JSON.stringify(self.deviceList)); self.callback(); break; } case 2: { const count = self.deviceList.length; if (count > 0) { var list = []; for (var i = 0; i < count; i++) { if (self.deviceList[i].deviceId != data.device.deviceId) { list[i] = data.device; } } self.deviceList = list; } console.info('[RemoteDeviceModel] offline, updated device list=' + JSON.stringify(data.device)); self.callback(); break; } default: break; } });
- 说明:在不需要监听时需要取消注册的监听器,减少资源浪费。 接口:deviceManager.off(type: ‘deviceStateChange’, callback?: Callback<{ action: DeviceStateChangeAction, device: DeviceInfo }>): void。
- deviceManager.off('deviceStateChange');
- 关键字:deviceFound。 接口:deviceManager.on(type: ‘deviceFound’, callback: Callback<{ subscribeId: number, device: DeviceInfo }>): void。
- deviceManager.on(DEVICE_FOUND, (data) => { console.info('[RemoteDeviceModel] deviceFound data=' + JSON.stringify(data)); if (data == null) { return; } const count = self.discoverList.length; for (var i = 0; i < count; i++) { if (self.discoverList[i].deviceId === data.device.deviceId) { // 设备已经在列表中 return; } } // 新增发现的设备 self.discoverList[count] = data.device; self.callback(); });
- 说明:在不需要监听时需要取消注册的监听器,减少资源浪费。 接口:deviceManager.off(type: ‘deviceFound’, callback?: Callback<{ subscribeId: number, device: DeviceInfo }>): void。
- deviceManager.off('deviceFound');
- 说明:认证指定的设备 接口:deviceManager.authenticateDevice(deviceInfo: DeviceInfo, authParam: AuthParam, callback: AsyncCallback<{deviceId: string, pinTone ?: number}>): void。
- 参数:AuthParam。
- authDevice(deviceId, callback) { console.info('[RemoteDeviceModel] authDevice ' + deviceId); for (var i = 0; i < this.discoverList.length; i++) { if (this.discoverList[i].deviceId === deviceId) { // 在线设备中存在此设备,创建扩展信息 let extraInfo = { "targetPkgName": 'com.nlas.myapplication', "appName": 'demo', "appDescription": 'demo application', "business": '0' }; let authParam = { "authType": 1,// 认证类型,1为pin码。 "appIcon": '', "appThumbnail": '', "extraInfo": extraInfo // 扩展信息:key-value }; console.info('[RemoteDeviceModel] authenticateDevice ' + JSON.stringify(this.discoverList[i])); this.authDeviceInfo = this.discoverList[i]; let self = this; this.#deviceManager.authenticateDevice(this.authDeviceInfo, authParam, (err, data)=>{ if (err) { console.info('[RemoteDeviceModel] authenticateDevice failed, err=' + JSON.stringify(err)); self.authCallback = null; } else { console.info('[RemoteDeviceModel] authenticateDevice succeed, data=' + JSON.stringify(data)); self.authCallback = callback; } }) } } }
- 说明:通过@ohos.ability.featureAbility 提供的 startAbility() 接口启动远程的FA。 接口:featureAbility.startAbility(parameter: StartAbilityParameter): Promise。
- 启动新的ability(Promise形式)。 参数:StartAbilityParameter。 参数:Want。 参数:flags说明。
- startAbilityContinuation(deviceId, deviceName) { this.$element('continueAbilityDialog').close(); console.info('featureAbility.startAbility deviceId=' + deviceId + ' deviceName=' + deviceName); const wantValue = { bundleName: 'com.nlas.myapplication', abilityName: 'com.nlas.myapplication.MainAbility', deviceId: deviceId }; featureAbility.startAbility({ want: wantValue }).then((data) => { console.info('featureAbility.startAbility finished, ' + JSON.stringify(data)); }); console.info('featureAbility.startAbility want=' + JSON.stringify(wantValue)); }, 到此为止,OpenHarmony分布式调度启动远程FA的实现,如果有地方介绍有错误请指正。 完整代码:https://ost.51cto.com/resource/1883。 想了解更多内容,请访问: 51CTO OpenHarmony技术社区 https://ost.51cto.com

基于OpenHarmony提供的分布式能力,实现在同一个网络下拉起远程设备的Ability,本节主要分享分布式中最基础的能力,分布式拉起的实现。

- 系统版本:OpenHarmony 3.1 release
- SDK:OpenHarmony API 8
- 设备:Hi3516
- IDE:DevEco Studio 3.0 Beta3
- PC:win10 64
1、在Hi3616开发板上烧写OpenHarmony 3.1 release系统。
2、准备两台烧录相同的版本系统的Hi3516DV300开发板A,B。
3、两个开发板A,B配置在同一个WiFi网络之下。打开设置–>WLAN–>点击右侧WiFi开关–>点击目标WiFi并输入密钥。
以下内容是本地学习和整理的材料,如果有不对的地方请留言指正,谢谢。

1、用户授权,分布式启动远程FA需要申请敏感权限:ohos.permission.DISTRIBUTED_DATASYNC,用户授权成功后才可以使用。
2、通过deviceManager.createDeviceManager()创建设备管理对象实例DeviceManager。
3、同步获取所有可信设备列表:deviceManager.getTrustedDeviceListSync()。
4、启动发现设备:deviceManager.startDeviceDiscovery()。
5、注册监听器:deviceManager.on()。
- deviceStateChange:设备状态发生改变,比如上班上线、下线、状态同步完成。
- deviceFound:发现设备。
- discoverFail:发现设备失败。
- serviceDie:服务停止。
6、设备认证:deviceManager.authenticateDevice(),两台设备互联需要先建立认证,认证通过两台设备即为可信设备,可以进行一些分布式操作。
7、启动远端FA,featureAbility.startAbility(),其中featureAbility是@ohos.ability.featureAbility。
说明:需要申请的权限可以在config.json的module模块中进行声明。
module{
"reqPermissions": [
{
"name": "ohos.permission.DISTRIBUTED_DATASYNC"
}
]
}
说明:敏感权限需要用户授权后才可以访问,本案例应用启动就需要申请,所以在index.js的onInit()方法中申请。
AbilityContext.requestPermissionsFromUser(permissions: Array<string>, requestCallback: AsyncCallback<PermissionRequestResult>) : void;

参数:PermissionRequestResult。
说明:权限请求结果。
备注:本模块首批接口从API 9开始支持。后续版本的新增接口,采用上角标单独标记接口的起始版本。

grantPermission() {
let context = featureAbility.getContext();
context.requestPermissionsFromUser(REQUEST_PERMISSION_LIST, REQUEST_PERMISSION_CODE, function(result){
console.log('request Permissions From User Result:' + JSON.stringify(result));
// todo 判断是否授权
}
}
let context = featureAbility.getContext();
context.requestPermissionsFromUser(REQUEST_PERMISSION_LIST, REQUEST_PERMISSION_CODE, function(result){
console.log('request Permissions From User Result:' + JSON.stringify(result));
// todo 判断是否授权
}
}
获取DeviceManager实例:
说明:需要操作设备必须获取设备实例才可以=,ohos.distributedHardware.deviceManager中提供了创建的方法:createDeviceManager(bundleName: string, callback: AsyncCallback): void。
备注:DeviceManager API

registerDeviceListCallback(callback) {
if (typeof (this.#deviceManager) === 'undefined') {
// 获取设备管理对象
let self = this;
deviceManager.createDeviceManager('com.nlas.myapplication',
(error, value) => {
if (error) {
console.error('createDeviceManager failed.');
return;
}
self.#deviceManager = value;// 设备管理器对象实例
// 执行操作...
})
} else {
// 设备管理器对象已经存在,直接可以执行操作...
}
}
if (typeof (this.#deviceManager) === 'undefined') {
// 获取设备管理对象
let self = this;
deviceManager.createDeviceManager('com.nlas.myapplication',
(error, value) => {
if (error) {
console.error('createDeviceManager failed.');
return;
}
self.#deviceManager = value;// 设备管理器对象实例
// 执行操作...
})
} else {
// 设备管理器对象已经存在,直接可以执行操作...
}
}
说明:同步获取所有可信设备列表
deviceManager.getTrustedDeviceListSync(): Array。

// 同步获取所有可信设备列表
var list = this.#deviceManager.getTrustedDeviceListSync();
console.info('[RemoteDeviceModel] deviceList=' + JSON.stringify(list));
var list = this.#deviceManager.getTrustedDeviceListSync();
console.info('[RemoteDeviceModel] deviceList=' + JSON.stringify(list));
接口:deviceManager.startDeviceDiscovery(subscribeInfo: SubscribeInfo):void。

参数:SubscribeInfo。

// 随机数
SUBSCRIBE_ID = Math.floor(65536 * Math.random());
var info = {
subscribeId: SUBSCRIBE_ID,// 服务订阅ID【0~65535】,对每个发现进程来说应该是唯一的
mode: 0xAA,//主动模式
medium: 2,//订阅媒介 2-wifi
freq: 2,// 订阅频率 高
isSameAccount: false,// 只能找到帐号相同的设备
isWakeRemote: true,// 发现休眠设备
capability: 0
};
console.info('[RemoteDeviceModel] startDeviceDiscovery ' + SUBSCRIBE_ID);
deviceManager.startDeviceDiscovery(info);// 发现设备
SUBSCRIBE_ID = Math.floor(65536 * Math.random());
var info = {
subscribeId: SUBSCRIBE_ID,// 服务订阅ID【0~65535】,对每个发现进程来说应该是唯一的
mode: 0xAA,//主动模式
medium: 2,//订阅媒介 2-wifi
freq: 2,// 订阅频率 高
isSameAccount: false,// 只能找到帐号相同的设备
isWakeRemote: true,// 发现休眠设备
capability: 0
};
console.info('[RemoteDeviceModel] startDeviceDiscovery ' + SUBSCRIBE_ID);
deviceManager.startDeviceDiscovery(info);// 发现设备
注册设备状态回调。
关键字:deviceStateChange。
接口:deviceManager.on(type: ‘deviceStateChange’, callback: Callback<{ action: DeviceStateChangeAction, device: DeviceInfo }>): void。

参数:DeviceStateChangeAction。
说明:表示设备状态变化的枚举。

参数:DeviceInfo。
说明:设备信息。

参数:DeviceType。
说明:表示设备类型的枚举类。

deviceManager.on(DEVICE_STATE_CHANGE, (data) => {
console.info('[RemoteDeviceModel] deviceStateChange data=' + JSON.stringify(data));
if (data == null) {
return;
}
switch (data.action) {
case 0:
{
self.deviceList[self.deviceList.length] = data.device;
console.info('[RemoteDeviceModel] online, updated device list=' + JSON.stringify(self.deviceList));
self.callback();
if (self.authCallback != null) {
self.authCallback();
self.authCallback = null;
}
break;
}
case 1:
{
if (self.deviceList.length > 0) {
for (var i = 0; i < self.deviceList.length; i++) {
if (self.deviceList[i].deviceId === data.device.deviceId) {
self.deviceList[i] = data.device;
break;
}
}
}
console.info('[RemoteDeviceModel] change, updated device list=' + JSON.stringify(self.deviceList));
self.callback();
break;
}
case 2:
{
const count = self.deviceList.length;
if (count > 0) {
var list = [];
for (var i = 0; i < count; i++) {
if (self.deviceList[i].deviceId != data.device.deviceId) {
list[i] = data.device;
}
}
self.deviceList = list;
}
console.info('[RemoteDeviceModel] offline, updated device list=' + JSON.stringify(data.device));
self.callback();
break;
}
default:
break;
}
});
console.info('[RemoteDeviceModel] deviceStateChange data=' + JSON.stringify(data));
if (data == null) {
return;
}
switch (data.action) {
case 0:
{
self.deviceList[self.deviceList.length] = data.device;
console.info('[RemoteDeviceModel] online, updated device list=' + JSON.stringify(self.deviceList));
self.callback();
if (self.authCallback != null) {
self.authCallback();
self.authCallback = null;
}
break;
}
case 1:
{
if (self.deviceList.length > 0) {
for (var i = 0; i < self.deviceList.length; i++) {
if (self.deviceList[i].deviceId === data.device.deviceId) {
self.deviceList[i] = data.device;
break;
}
}
}
console.info('[RemoteDeviceModel] change, updated device list=' + JSON.stringify(self.deviceList));
self.callback();
break;
}
case 2:
{
const count = self.deviceList.length;
if (count > 0) {
var list = [];
for (var i = 0; i < count; i++) {
if (self.deviceList[i].deviceId != data.device.deviceId) {
list[i] = data.device;
}
}
self.deviceList = list;
}
console.info('[RemoteDeviceModel] offline, updated device list=' + JSON.stringify(data.device));
self.callback();
break;
}
default:
break;
}
});
说明:在不需要监听时需要取消注册的监听器,减少资源浪费。
接口:deviceManager.off(type: ‘deviceStateChange’, callback?: Callback<{ action:
DeviceStateChangeAction, device: DeviceInfo }>): void。
deviceManager.off('deviceStateChange');
关键字:deviceFound。
接口:deviceManager.on(type: ‘deviceFound’, callback: Callback<{ subscribeId: number, device:
DeviceInfo }>): void。

deviceManager.on(DEVICE_FOUND, (data) => {
console.info('[RemoteDeviceModel] deviceFound data=' + JSON.stringify(data));
if (data == null) {
return;
}
const count = self.discoverList.length;
for (var i = 0; i < count; i++) {
if (self.discoverList[i].deviceId === data.device.deviceId) {
// 设备已经在列表中
return;
}
}
// 新增发现的设备
self.discoverList[count] = data.device;
self.callback();
});
console.info('[RemoteDeviceModel] deviceFound data=' + JSON.stringify(data));
if (data == null) {
return;
}
const count = self.discoverList.length;
for (var i = 0; i < count; i++) {
if (self.discoverList[i].deviceId === data.device.deviceId) {
// 设备已经在列表中
return;
}
}
// 新增发现的设备
self.discoverList[count] = data.device;
self.callback();
});
说明:在不需要监听时需要取消注册的监听器,减少资源浪费。
接口:deviceManager.off(type: ‘deviceFound’, callback?: Callback<{ subscribeId: number, device:
DeviceInfo }>): void。
deviceManager.off('deviceFound');
说明:认证指定的设备
接口:deviceManager.authenticateDevice(deviceInfo: DeviceInfo, authParam: AuthParam, callback:
AsyncCallback<{deviceId: string, pinTone ?: number}>): void。

参数:AuthParam。

authDevice(deviceId, callback) {
console.info('[RemoteDeviceModel] authDevice ' + deviceId);
for (var i = 0; i < this.discoverList.length; i++) {
if (this.discoverList[i].deviceId === deviceId) {
// 在线设备中存在此设备,创建扩展信息
let extraInfo = {
"targetPkgName": 'com.nlas.myapplication',
"appName": 'demo',
"appDescription": 'demo application',
"business": '0'
};
let authParam = {
"authType": 1,// 认证类型,1为pin码。
"appIcon": '',
"appThumbnail": '',
"extraInfo": extraInfo // 扩展信息:key-value
};
console.info('[RemoteDeviceModel] authenticateDevice ' + JSON.stringify(this.discoverList[i]));
this.authDeviceInfo = this.discoverList[i];
let self = this;
this.#deviceManager.authenticateDevice(this.authDeviceInfo, authParam, (err, data)=>{
if (err) {
console.info('[RemoteDeviceModel] authenticateDevice failed, err=' + JSON.stringify(err));
self.authCallback = null;
} else {
console.info('[RemoteDeviceModel] authenticateDevice succeed, data=' + JSON.stringify(data));
self.authCallback = callback;
}
})
}
}
}
console.info('[RemoteDeviceModel] authDevice ' + deviceId);
for (var i = 0; i < this.discoverList.length; i++) {
if (this.discoverList[i].deviceId === deviceId) {
// 在线设备中存在此设备,创建扩展信息
let extraInfo = {
"targetPkgName": 'com.nlas.myapplication',
"appName": 'demo',
"appDescription": 'demo application',
"business": '0'
};
let authParam = {
"authType": 1,// 认证类型,1为pin码。
"appIcon": '',
"appThumbnail": '',
"extraInfo": extraInfo // 扩展信息:key-value
};
console.info('[RemoteDeviceModel] authenticateDevice ' + JSON.stringify(this.discoverList[i]));
this.authDeviceInfo = this.discoverList[i];
let self = this;
this.#deviceManager.authenticateDevice(this.authDeviceInfo, authParam, (err, data)=>{
if (err) {
console.info('[RemoteDeviceModel] authenticateDevice failed, err=' + JSON.stringify(err));
self.authCallback = null;
} else {
console.info('[RemoteDeviceModel] authenticateDevice succeed, data=' + JSON.stringify(data));
self.authCallback = callback;
}
})
}
}
}
说明:通过@ohos.ability.featureAbility 提供的 startAbility() 接口启动远程的FA。
接口:featureAbility.startAbility(parameter: StartAbilityParameter): Promise。
启动新的ability(Promise形式)。

参数:StartAbilityParameter。

参数:Want。

参数:flags说明。

startAbilityContinuation(deviceId, deviceName) {
this.$element('continueAbilityDialog').close();
console.info('featureAbility.startAbility deviceId=' + deviceId
+ ' deviceName=' + deviceName);
const wantValue = {
bundleName: 'com.nlas.myapplication',
abilityName: 'com.nlas.myapplication.MainAbility',
deviceId: deviceId
};
featureAbility.startAbility({
want: wantValue
}).then((data) => {
console.info('featureAbility.startAbility finished, ' + JSON.stringify(data));
});
console.info('featureAbility.startAbility want=' + JSON.stringify(wantValue));
},
this.$element('continueAbilityDialog').close();
console.info('featureAbility.startAbility deviceId=' + deviceId
+ ' deviceName=' + deviceName);
const wantValue = {
bundleName: 'com.nlas.myapplication',
abilityName: 'com.nlas.myapplication.MainAbility',
deviceId: deviceId
};
featureAbility.startAbility({
want: wantValue
}).then((data) => {
console.info('featureAbility.startAbility finished, ' + JSON.stringify(data));
});
console.info('featureAbility.startAbility want=' + JSON.stringify(wantValue));
},
到此为止,OpenHarmony分布式调度启动远程FA的实现,如果有地方介绍有错误请指正。
完整代码:https://ost.51cto.com/resource/1883。
