华为Harmony鸿蒙开发笔记六:Ability跨设备分布式任务调度
目前来看,鸿蒙应用的跨设备分布式调度并不复杂,跟在本应用内调用没有太大却别,只是多了权限管理和设备管理的相关参数和配置。这里我将官方文档的代码整理一下,等待以后验证。首先配置权限,根据已经验证了的DataAbility可知,权限是配置在请求方的Ability的配置文件里的{"skills": [{"entities": ["entity.system.home"
·
目前来看,鸿蒙应用的跨设备分布式调度并不复杂,跟在本应用内调用没有太大却区别,只是多了权限管理和设备管理的相关参数和配置。
这里我将官方文档的代码整理一下,等待以后验证。
首先配置权限,根据已经验证了的DataAbility可知,权限是配置在请求方的Ability的配置文件里的
{
"skills": [
{
"entities": [
"entity.system.home"
],
"actions": [
"action.system.home"
]
}
],
"orientation": "unspecified",
"name": "com.example.distributeddemo.MainAbility",
"icon": "$media:icon",
"description": "$string:mainability_description",
"label": "DistributedDemo",
"type": "page",
"launchType": "standard",
"reqPermissions": [
{
"name": "ohos.permission.DISTRIBUTED_DATASYNC"
}
]
}
上面reqPermissions就是配置权限,使该Ability支持任务调度,然后就是改造AbilitySlice
首先要实现IAbilityContinuation接口,并实现接口方法,并在onStart里显式申明权限
public class SampleSlice extends AbilitySlice implements IAbilityContinuation {
@Override
public void onStart(Intent intent) {
// 开发者显示声明需要使用的权限
requestPermissionsFromUser(new String[]{"ohos.permission.DISTRIBUTED_DATASYNC"}, 0);
super.onStart(intent);
}
}
然后编写UI,添加几个按钮:
<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayout
xmlns:ohos="http://schemas.huawei.com/res/ohos"
ohos:height="match_parent"
ohos:width="match_parent"
ohos:orientation="vertical">
<Button
ohos:id="$+id:btn_start_remote_fa"
ohos:width="match_content"
ohos:height="match_content"
ohos:text="远程启动FA"
ohos:text_size="19fp"
ohos:text_color="#FFFFFF"
ohos:top_padding="8vp"
ohos:layout_alignment="center"
ohos:bottom_padding="8vp"
ohos:right_padding="70vp"
ohos:left_padding="70vp"
ohos:top_margin="10vp"
ohos:background_element="$graphic:background_button"
ohos:center_in_parent="true"
ohos:bottom_margin="10vp"/>
<Button
ohos:id="$+id:btn_continue_remote_fa"
ohos:width="match_content"
ohos:height="match_content"
ohos:text="远程迁移FA"
ohos:text_size="19fp"
ohos:text_color="#FFFFFF"
ohos:top_padding="8vp"
ohos:layout_alignment="center"
ohos:bottom_padding="8vp"
ohos:right_padding="70vp"
ohos:left_padding="70vp"
ohos:top_margin="10vp"
ohos:background_element="$graphic:background_button"
ohos:center_in_parent="true"
ohos:bottom_margin="10vp"/>
<Button
ohos:id="$+id:btn_start_remote_pa"
ohos:width="match_content"
ohos:height="match_content"
ohos:text="远程启动PA"
ohos:text_size="19fp"
ohos:text_color="#FFFFFF"
ohos:top_padding="8vp"
ohos:layout_alignment="center"
ohos:bottom_padding="8vp"
ohos:right_padding="70vp"
ohos:left_padding="70vp"
ohos:top_margin="10vp"
ohos:background_element="$graphic:background_button"
ohos:center_in_parent="true"
ohos:bottom_margin="10vp"/>
<Button
ohos:id="$+id:btn_stop_remote_pa"
ohos:width="match_content"
ohos:height="match_content"
ohos:text="远程关闭PA"
ohos:text_size="19fp"
ohos:text_color="#FFFFFF"
ohos:top_padding="8vp"
ohos:layout_alignment="center"
ohos:bottom_padding="8vp"
ohos:right_padding="70vp"
ohos:left_padding="70vp"
ohos:top_margin="10vp"
ohos:background_element="$graphic:background_button"
ohos:center_in_parent="true"
ohos:bottom_margin="10vp"/>
<Button
ohos:id="$+id:btn_connect_remote_pa"
ohos:width="match_content"
ohos:height="match_content"
ohos:text="连接远程PA"
ohos:text_size="19fp"
ohos:text_color="#FFFFFF"
ohos:top_padding="8vp"
ohos:layout_alignment="center"
ohos:bottom_padding="8vp"
ohos:right_padding="70vp"
ohos:left_padding="70vp"
ohos:top_margin="10vp"
ohos:background_element="$graphic:background_button"
ohos:center_in_parent="true"
ohos:bottom_margin="10vp"/>
<Button
ohos:id="$+id:btn_control_remote_pa"
ohos:width="match_content"
ohos:height="match_content"
ohos:text="控制连接PA"
ohos:text_size="19fp"
ohos:text_color="#FFFFFF"
ohos:top_padding="8vp"
ohos:layout_alignment="center"
ohos:bottom_padding="8vp"
ohos:right_padding="70vp"
ohos:left_padding="70vp"
ohos:top_margin="10vp"
ohos:background_element="$graphic:background_button"
ohos:center_in_parent="true"
ohos:bottom_margin="10vp"/>
<Button
ohos:id="$+id:btn_disconnect_remote_pa"
ohos:width="match_content"
ohos:height="match_content"
ohos:text="断开远程PA"
ohos:text_size="19fp"
ohos:text_color="#FFFFFF"
ohos:top_padding="8vp"
ohos:layout_alignment="center"
ohos:bottom_padding="8vp"
ohos:right_padding="70vp"
ohos:left_padding="70vp"
ohos:top_margin="10vp"
ohos:background_element="$graphic:background_button"
ohos:center_in_parent="true"
ohos:bottom_margin="10vp"/>
</DirectionalLayout>
初始化按钮,并添加点击事件:
private MyRemoteProxy mProxy = null;
private Button btnConnectRemotePA;
private Button btnControlRemotePA;
private Button btnContinueRemoteFA;
@Override
public void onStart(Intent intent) {
super.onStart(intent);
super.setUIContent(ResourceTable.Layout_ability_main);
requestPermissionsFromUser(new String[]{"ohos.permission.DISTRIBUTED_DATASYNC"}, 0);
InsideListener listener = new InsideListener();
findComponentById(ResourceTable.Id_btn_start_remote_fa).setClickedListener(listener);
findComponentById(ResourceTable.Id_btn_start_remote_pa).setClickedListener(listener);
findComponentById(ResourceTable.Id_btn_stop_remote_pa).setClickedListener(listener);
btnContinueRemoteFA = (Button) findComponentById(ResourceTable.Id_btn_continue_remote_fa);
btnContinueRemoteFA.setClickedListener(listener);
btnConnectRemotePA = (Button) findComponentById(ResourceTable.Id_btn_connect_remote_pa);
btnConnectRemotePA.setClickedListener(listener);
btnControlRemotePA = (Button) findComponentById(ResourceTable.Id_btn_control_remote_pa);
btnControlRemotePA.setClickedListener(listener);
findComponentById(ResourceTable.Id_btn_disconnect_remote_pa).setClickedListener(listener);
}
class InsideListener implements Component.ClickedListener {
@Override
public void onClick(Component component) {
switch (component.getId()) {
case ResourceTable.Id_btn_start_remote_fa:
HiLog.info(LABEL_LOG, "MainAbilitySlice btn_start_remote_fa");
break;
case ResourceTable.Id_btn_continue_remote_fa:
HiLog.info(LABEL_LOG, "MainAbilitySlice btn_continue_remote_fa");
break;
case ResourceTable.Id_btn_start_remote_pa:
HiLog.info(LABEL_LOG, "MainAbilitySlice btn_start_remote_pa");
break;
case ResourceTable.Id_btn_stop_remote_pa:
HiLog.info(LABEL_LOG, "MainAbilitySlice btn_stop_remote_pa");
break;
case ResourceTable.Id_btn_connect_remote_pa:
HiLog.info(LABEL_LOG, "MainAbilitySlice btn_connect_remote_pa");
break;
case ResourceTable.Id_btn_control_remote_pa:
HiLog.info(LABEL_LOG, "MainAbilitySlice btn_control_remote_pa");
break;
case ResourceTable.Id_btn_disconnect_remote_pa:
HiLog.info(LABEL_LOG, "MainAbilitySlice btn_disconnect_remote_pa");
break;
default:
break;
}
}
}
通过设备管理DeviceManager提供的getDeviceList接口获取设备列表,并选择一个设备:
// ISelectResult是一个自定义接口,用来处理指定设备deviceId后执行的行为
interface ISelectResult {
void onSelectResult(String deviceId);
}
// 获得设备列表,开发者可在得到的在线设备列表中选择目标设备执行操作
private void scheduleRemoteAbility(ISelectResult listener) {
// 调用DeviceManager的getDeviceList接口,通过FLAG_GET_ONLINE_DEVICE标记获得在线设备列表
List<DeviceInfo> onlineDevices = DeviceManager.getDeviceList(DeviceInfo.FLAG_GET_ONLINE_DEVICE);
// 判断组网设备是否为空
if (onlineDevices.isEmpty()) {
listener.onSelectResult(null);
return;
}
int numDevices = onlineDevices.size();
ArrayList<String> deviceIds = new ArrayList<>(numDevices);
ArrayList<String> deviceNames = new ArrayList<>(numDevices);
onlineDevices.forEach((device) -> {
deviceIds.add(device.getDeviceId());
deviceNames.add(device.getDeviceName());
});
// 以选择首个设备作为目标设备为例
// 开发者也可按照具体场景,通过别的方式进行设备选择
String selectDeviceId = deviceIds.get(0);
listener.onSelectResult(selectDeviceId);
}
各个按钮对应的点击事件:
class InsideListener implements Component.ClickedListener {
@Override
public void onClick(Component component) {
switch (component.getId()) {
case ResourceTable.Id_btn_start_remote_fa:
HiLog.info(LABEL_LOG, "MainAbilitySlice btn_start_remote_fa");
// 启动远程PA
scheduleRemoteAbility(new ISelectResult() {
@Override
public void onSelectResult(String deviceId) {
if (deviceId != null) {
Intent intent = new Intent();
// 通过scheduleRemoteAbility指定目标设备deviceId
// 指定待启动FA的bundleName和abilityName
// 例如:bundleName = "com.huawei.helloworld"
// abilityName = "com.huawei.helloworld.SampleFeatureAbility"
// 设置分布式标记,表明当前涉及分布式能力
Operation operation = new Intent.OperationBuilder()
.withDeviceId(deviceId)
.withBundleName("目标bundleName")
.withAbilityName("目标abilityName")
.withFlags(Intent.FLAG_ABILITYSLICE_MULTI_DEVICE)
.build();
intent.setOperation(operation);
// 通过AbilitySlice包含的startAbility接口实现跨设备启动FA
startAbility(intent);
}
}
});
break;
case ResourceTable.Id_btn_continue_remote_fa:
HiLog.info(LABEL_LOG, "MainAbilitySlice btn_continue_remote_fa");
// 用户选择设备后实现业务迁移
scheduleRemoteAbility(new ISelectResult() {
@Override
public void onSelectResult(String deviceId) {
continueAbility(deviceId);
}
});
break;
case ResourceTable.Id_btn_start_remote_pa:
HiLog.info(LABEL_LOG, "MainAbilitySlice btn_start_remote_pa");
// 启动远程PA
scheduleRemoteAbility(new ISelectResult() {
@Override
public void onSelectResult(String deviceId) {
if (deviceId != null) {
Intent intentToStartPA = new Intent();
// bundleName和abilityName与待启动PA对应
// 例如:bundleName = "com.huawei.helloworld"
// abilityName = "com.huawei.helloworld.SampleParticleAbility"
Operation operation = new Intent.OperationBuilder()
.withDeviceId(deviceId)
.withBundleName("目标bundleName")
.withAbilityName("目标abilityName")
.withFlags(Intent.FLAG_ABILITYSLICE_MULTI_DEVICE)
.build();
intentToStartPA.setOperation(operation);
startAbility(intentToStartPA);
}
}
});
break;
case ResourceTable.Id_btn_stop_remote_pa:
HiLog.info(LABEL_LOG, "MainAbilitySlice btn_stop_remote_pa");
scheduleRemoteAbility(new ISelectResult() {
@Override
public void onSelectResult(String deviceId) {
if (deviceId != null) {
Intent intentToStopPA = new Intent();
// bundleName和abilityName与待关闭PA对应
// 例如:bundleName = "com.huawei.helloworld"
// abilityName = "com.huawei.helloworld.SampleParticleAbility"
Operation operation = new Intent.OperationBuilder()
.withDeviceId(deviceId)
.withBundleName("目标bundleName")
.withAbilityName("目标abilityName")
.withFlags(Intent.FLAG_ABILITYSLICE_MULTI_DEVICE)
.build();
intentToStopPA.setOperation(operation);
stopAbility(intentToStopPA);
}
}
});
break;
case ResourceTable.Id_btn_connect_remote_pa:
HiLog.info(LABEL_LOG, "MainAbilitySlice btn_connect_remote_pa");
scheduleRemoteAbility(new ISelectResult() {
@Override
public void onSelectResult(String deviceId) {
if (deviceId != null) {
Intent connectPAIntent = new Intent();
// bundleName和abilityName与待连接的PA一一对应
// 例如:bundleName = "com.huawei.helloworld"
// abilityName = "com.huawei.helloworld.SampleParticleAbility"
Operation operation = new Intent.OperationBuilder()
.withDeviceId(deviceId)
.withBundleName("目标bundleName")
.withAbilityName("目标abilityName")
.withFlags(Intent.FLAG_ABILITYSLICE_MULTI_DEVICE)
.build();
connectPAIntent.setOperation(operation);
connectAbility(connectPAIntent, conn);
}
}
});
break;
case ResourceTable.Id_btn_control_remote_pa:
HiLog.info(LABEL_LOG, "MainAbilitySlice btn_control_remote_pa");
if (mProxy != null) {
int ret = -1;
try {
ret = mProxy.plus(10, 20);
} catch (RemoteException e) {
e.printStackTrace();
}
btnControlRemotePA.setText("控制连接 result = " + ret);
}
break;
case ResourceTable.Id_btn_disconnect_remote_pa:
HiLog.info(LABEL_LOG, "MainAbilitySlice btn_disconnect_remote_pa");
btnConnectRemotePA.setText("连接远程PA");
btnControlRemotePA.setText("控制连接PA");
disconnectAbility(conn);
break;
default:
break;
}
}
}
最后,FA跨设备迁移的生命周期方法:
流程参见;https://blog.csdn.net/y280903468/article/details/111770977
@Override
public boolean onSaveData(IntentParams saveData) {
String exampleData = String.valueOf(System.currentTimeMillis());
saveData.setParam("continueParam", exampleData);
return true;
}
@Override
public boolean onRestoreData(IntentParams restoreData) {
// 远端FA迁移传来的状态数据,开发者可以按照特定的场景对这些数据进行处理
Object data = restoreData.getParam("continueParam");
return true;
}
@Override
public void onCompleteContinuation(int result) {
btnContinueRemoteFA.setText("ContinueAbility Done");
}
更多推荐



所有评论(0)