1. 分布式任務(wù)調(diào)度概述
在HarmonyOS中,分布式任務(wù)調(diào)度平臺對搭載HarmonyOS的多設(shè)備構(gòu)筑的“超級虛擬終端”提供統(tǒng)一的組件管理能力,為應(yīng)用定義統(tǒng)一的能力基線、接口形式、數(shù)據(jù)結(jié)構(gòu)、服務(wù)描述語言,屏蔽硬件差異;支持遠(yuǎn)程啟動、遠(yuǎn)程調(diào)用、業(yè)務(wù)無縫遷移等分布式任務(wù)。
2. 實現(xiàn)調(diào)度的約束與限制
1)遠(yuǎn)程調(diào)用PA/FA,開發(fā)者需要在Intent中設(shè)置支持分布式的標(biāo)記(例如:Intent.FLAG_ABILITYSLICE_MULTI_DEVICE表示該應(yīng)用支持分布式調(diào)度),否則將無法獲得分布式能力。
2)開發(fā)者通過在config.json中的reqPermissions字段里添加權(quán)限申請:
(1)以獲取跨設(shè)備連接的能力和分布式數(shù)據(jù)傳輸?shù)臋?quán)限。
分布式數(shù)據(jù)傳輸?shù)臋?quán)限:
{“name”: “ohos.permission.servicebus.ACCESS_SERVICE”}
三方應(yīng)用使用權(quán)限:
{“name”: “ohos.permission.servicebus.DISTRIBUTED_DATASYNC”}
系統(tǒng)應(yīng)用使用權(quán)限:
{“name”: “com.huawei.hwddmp.servicebus.BIND_SERVICE”}
(2)另外還有三個獲取分布式設(shè)備信息需要的權(quán)限:
{“name”: “ohos.permission.DISTRIBUTED_DEVICE_STATE_CHANGE”},
{“name”: “ohos.permission.GET_DISTRIBUTED_DEVICE_INFO” },
{ “name”: “ohos.permission.GET_BUNDLE_INFO”}
注意:還需要在開發(fā)的時候,要在Ability里主動聲明,要用到的權(quán)限。
3)FA(Feature Ability,Page模板的Ability)的調(diào)用支持啟動和遷移行為,在進(jìn)行調(diào)度時:
(1)當(dāng)啟動FA時,需要開發(fā)者在Intent中指定對端設(shè)備的deviceId、bundleName和abilityName。
(2)FA的遷移實現(xiàn)相同bundleName和abilityName的FA跨設(shè)備遷移,因此需要指定遷移設(shè)備的deviceId。
3. 實現(xiàn)場景介紹
下面以設(shè)備A(本地設(shè)備)和設(shè)備B(遠(yuǎn)端設(shè)備)為例,介紹下面我們要實現(xiàn)的場景:
1)設(shè)備A啟動設(shè)備B的FA:在設(shè)備A上通過本地應(yīng)用提供的啟動按鈕,啟動設(shè)備B上對應(yīng)的FA。
2)設(shè)備A的FA遷移至設(shè)備B:設(shè)備A上通過本地應(yīng)用提供的遷移按鈕,將設(shè)備A的業(yè)務(wù)無縫遷移到設(shè)備B中。
3)設(shè)備A的FA遷移至設(shè)備B,還可以實現(xiàn)主動撤回遷移。
4. 具體實現(xiàn)前先了解要用的接口
1)啟動遠(yuǎn)程FA
startAbility(Intent intent)接口提供啟動指定設(shè)備上FA和PA的能力,Intent中指定待啟動FA的設(shè)備deviceId、bundleName和abilityName。
2)遷移FA
continueAbility(String deviceId)接口提供將本地FA遷移到指定設(shè)備上的能力,continueAbilityReversibly(String deviceId) 接口提供將本地FA遷移到指定設(shè)備上的能力,這種遷移可撤回, reverseContinueAbility()接口提供撤回遷移的能力。
5. 實戰(zhàn)遠(yuǎn)程啟動FA頁面
1)編程實現(xiàn)上面場景的界面:
ability_main.xml
《?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:migration_btn_01”
ohos:height=“match_content”
ohos:width=“300vp”
ohos:text=“1.啟動遠(yuǎn)程設(shè)備的FA”
ohos:text_size=“20fp”
ohos:text_color=“#ffffff”
ohos:background_element=“$graphic:button_bg”
ohos:layout_alignment=“horizontal_center”
ohos:top_padding=“8vp”
ohos:bottom_padding=“8vp”
ohos:left_padding=“40vp”
ohos:right_padding=“40vp”
ohos:top_margin=“20vp”
/》
《Button
ohos:id=“$+id:migration_btn_02”
ohos:height=“match_content”
ohos:width=“300vp”
ohos:text=“2.遷移到遠(yuǎn)程設(shè)備”
ohos:text_size=“20fp”
ohos:text_color=“#ffffff”
ohos:background_element=“$graphic:button_bg”
ohos:layout_alignment=“horizontal_center”
ohos:top_padding=“8vp”
ohos:bottom_padding=“8vp”
ohos:left_padding=“40vp”
ohos:right_padding=“40vp”
ohos:top_margin=“20vp”
/》
《Button
ohos:id=“$+id:migration_btn_03”
ohos:height=“match_content”
ohos:width=“300vp”
ohos:text=“3.可遷回的遷移遠(yuǎn)程設(shè)備”
ohos:text_size=“20fp”
ohos:text_color=“#ffffff”
ohos:background_element=“$graphic:button_bg”
ohos:layout_alignment=“horizontal_center”
ohos:top_padding=“8vp”
ohos:bottom_padding=“8vp”
ohos:left_padding=“40vp”
ohos:right_padding=“40vp”
ohos:top_margin=“20vp”
/》
《/DirectionalLayout》1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.28.29.30.31.32.33.34.35.36.37.38.39.40.41.42.43.44.45.46.47.48.49.50.51.52.53.54.55.56.
復(fù)制button_bg.xml
《?xml version=“1.0” encoding=“utf-8”?》
《shape xmlns:ohos=“http://schemas.huawei.com/res/ohos”
ohos:shape=“rectangle”》
《solid ohos:color=“#007DFF”/》
《corners ohos:radius=“40”/》
《/shape》1.2.3.4.5.6.
復(fù)制MigrationAbility和MigrationBackAbility
// 調(diào)用AbilitySlice模板實現(xiàn)一個用于控制基礎(chǔ)功能的FA
// Ability和AbilitySlice類均需要實現(xiàn)IAbilityContinuation及其方法,才可以實現(xiàn)FA遷移。AbilitySlice的代碼示例如下
public class SampleSlice extends AbilitySlice implements IAbilityContinuation {
@Override
public void onStart(Intent intent) {
super.onStart(intent);
super.setUIContent(layout);
}1.2.3.4.5.6.7.8.9.
復(fù)制ability_migration.xml
《?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:background_element=“#00ffff”
ohos:orientation=“vertical”》
《Text
ohos:id=“$+id:text_title”
ohos:height=“match_content”
ohos:width=“250vp”
ohos:background_element=“#0088bb”
ohos:layout_alignment=“horizontal_center”
ohos:text=“下面是一個可編輯的文本框”
ohos:text_size=“50”
ohos:padding=“5vp”
ohos:top_margin=“30vp”
/》
《TextField
ohos:id=“$+id:textfield_back”
ohos:height=“250vp”
ohos:width=“250vp”
ohos:hint=“請輸入。。.”
ohos:layout_alignment=“horizontal_center”
ohos:background_element=“#ffffff”
ohos:text_color=“#888888”
ohos:text_size=“20fp”
ohos:padding=“5vp”
/》
《Button
ohos:id=“$+id:migration_button”
ohos:height=“match_content”
ohos:width=“match_content”
ohos:text=“點擊遷移”
ohos:text_size=“20fp”
ohos:text_color=“#ffffff”
ohos:background_element=“$graphic:button_bg”
ohos:top_padding=“8vp”
ohos:bottom_padding=“8vp”
ohos:left_padding=“50vp”
ohos:right_padding=“50vp”
ohos:layout_alignment=“horizontal_center”
ohos:top_margin=“30vp”
/》
《/DirectionalLayout》1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.28.29.30.31.32.33.34.35.36.37.38.39.40.41.42.43.44.45.46.47.
復(fù)制ability_migration_back.xml比ability_migration.xml多一個遷回按鈕,另外主頁上點擊按鈕跳轉(zhuǎn)等,略。。.
2)使用分布式能力要求開發(fā)者在Ability對應(yīng)的config.json中聲明多設(shè)備協(xié)同訪問的權(quán)限:
(1)三方應(yīng)用部署權(quán)限、分布式數(shù)據(jù)傳輸?shù)臋?quán)限、系統(tǒng)應(yīng)用使用權(quán)限的申請。
{
“reqPermissions”: [
{“name”: “ohos.permission.DISTRIBUTED_DATASYNC”},
{“name”: “ohos.permission.servicebus.ACCESS_SERVICE”},
{“name”: “com.huawei.hwddmp.servicebus.BIND_SERVICE”}
]
}1.2.3.4.5.6.7.
復(fù)制(2)聲明分布式獲取設(shè)備列表及設(shè)備信息的權(quán)限,如下所示:
{
“reqPermissions”: [
{“name”: “ohos.permission.DISTRIBUTED_DEVICE_STATE_CHANGE”},
{“name”: “ohos.permission.GET_DISTRIBUTED_DEVICE_INFO” },
{“name”: “ohos.permission.GET_BUNDLE_INFO”}
]
}1.2.3.4.5.6.7.
復(fù)制(3)對于三方應(yīng)用還要求在實現(xiàn)Ability的代碼中顯式聲明需要使用的權(quán)限。
public class SampleSlice extends AbilitySlice implements IAbilityContinuation {
@Override
public void onStart(Intent intent) {
// 開發(fā)者顯示聲明需要使用的權(quán)限
requestPermissionsFromUser(new String[]{“ohos.permission.DISTRIBUTED_DATASYNC”,
“ohos.permission.servicebus.ACCESS_SERVICE”,
“com.huawei.hwddmp.servicebus.BIND_SERVICE”}, 0);
super.onStart(intent);
}
}1.2.3.4.5.6.7.8.9.10.
復(fù)制3) 為啟動遠(yuǎn)程FA的按鈕添加點擊事件,獲取設(shè)備信息,實現(xiàn)啟動遠(yuǎn)程FA的能力。
Button btn1 = (Button) findComponentById(ResourceTable.Id_migration_btn_01);
btn1.setClickedListener(new Component.ClickedListener() {
@Override
public void onClick(Component component) {
// 調(diào)用DeviceManager的getDeviceList接口,通過FLAG_GET_ONLINE_DEVICE標(biāo)記獲得在線設(shè)備列表
List《DeviceInfo》 onlineDevices = DeviceManager.getDeviceList(DeviceInfo.FLAG_GET_ONLINE_DEVICE);
// 判斷組網(wǎng)設(shè)備是否為空
if (onlineDevices.isEmpty()) {
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());
});
// 我們這里只有兩個設(shè)備,所以選擇首個設(shè)備作為目標(biāo)設(shè)備
// 開發(fā)者也可按照具體場景,通過別的方式進(jìn)行設(shè)備選擇
String selectDeviceId = deviceIds.get(0);
//獲取設(shè)備ID,最好放到工具類里,很多地方要用!
if(selectDeviceId!=null){
Intent intent2 = new Intent();
Operation operation = new Intent.OperationBuilder()
.withDeviceId(selectDeviceId)
.withBundleName(“cn.ybzy.hmsdemo”)
.withAbilityName(“cn.ybzy.hmsdemo.RemoteAbility”)
.withFlags(Intent.FLAG_ABILITYSLICE_MULTI_DEVICE)
.build();
intent2.setOperation(operation);
// 通過AbilitySlice包含的startAbility接口實現(xiàn)跨設(shè)備啟動FA
startAbility(intent2);
}
}
});1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.28.29.30.31.32.33.34.35.36.37.38.
復(fù)制6. 實戰(zhàn)將設(shè)備A運行時的FA遷移到設(shè)備B,實現(xiàn)業(yè)務(wù)在設(shè)備間無縫遷移。
MigrationAbility
public class MigrationAbility extends Ability implements IAbilityContinuation {
@Override
public void onStart(Intent intent) {
super.onStart(intent);
super.setMainRoute(MigrationAbilitySlice.class.getName());
}
@Override
public boolean onStartContinuation() {
return true;
}
@Override
public boolean onSaveData(IntentParams intentParams) {
return true;
}
@Override
public boolean onRestoreData(IntentParams intentParams) {
return true;
}
@Override
public void onCompleteContinuation(int i) {
}
}1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.
復(fù)制
MigrationAbilitySlice
public class MigrationAbilitySlice extends AbilitySlice implements IAbilityContinuation {
TextField textField;
String textStr = “請輸入數(shù)據(jù)。。.”;
@Override
public void onStart(Intent intent) {
super.onStart(intent);
super.setUIContent(ResourceTable.Layout_ability_migration);
textField = (TextField)findComponentById(ResourceTable.Id_textfield_migration);
textField.setText(textStr);
Button btn = (Button) findComponentById(ResourceTable.Id_migration_button);
btn.setClickedListener(new Component.ClickedListener() {
@Override
public void onClick(Component component) {
String deviceId = getDeviceId();
if(deviceId!=null){
continueAbility(deviceId);
}
}
});
}
private String getDeviceId(){
// 調(diào)用DeviceManager的getDeviceList接口,通過FLAG_GET_ONLINE_DEVICE標(biāo)記獲得在線設(shè)備列表
List《DeviceInfo》 onlineDevices = DeviceManager.getDeviceList(DeviceInfo.FLAG_GET_ONLINE_DEVICE);
// 判斷組網(wǎng)設(shè)備是否為空
if (onlineDevices.isEmpty()) {
return null;
}
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());
});
// 我們這里只有兩個設(shè)備,所以選擇首個設(shè)備作為目標(biāo)設(shè)備
// 開發(fā)者也可按照具體場景,通過別的方式進(jìn)行設(shè)備選擇
String selectDeviceId = deviceIds.get(0);
return selectDeviceId;
}
@Override
public boolean onStartContinuation() {
return true;
}
@Override
public boolean onSaveData(IntentParams intentParams) {
intentParams.setParam(“data”,textField.getText());
return true;
}
@Override
public boolean onRestoreData(IntentParams intentParams) {
textStr = intentParams.getParam(“data”).toString();
return true;
}
@Override
public void onCompleteContinuation(int i) {
}
@Override
public void onRemoteTerminated() {
}
}1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.28.29.30.31.32.33.34.35.36.37.38.39.40.41.42.43.44.45.46.47.48.49.50.51.52.53.54.55.56.57.58.59.60.61.62.63.64.65.66.67.68.69.70.
復(fù)制此外,不同于啟動行為,F(xiàn)A的遷移還涉及到狀態(tài)數(shù)據(jù)的傳遞。為此,繼承的IAbilityContinuation接口為開發(fā)者提供遷移過程中特定事件的管理能力。通過自定義遷移事件相關(guān)的行為,最終實現(xiàn)對Ability的遷移。主要以較為常用的兩個事件,包括遷移發(fā)起端完成遷移的回調(diào)onCompleteContinuation(int result)以及接收到遠(yuǎn)端遷移行為傳遞數(shù)據(jù)的回調(diào)onRestoreData(IntentParams restoreData)。其他還包括遷移到遠(yuǎn)端設(shè)備的FA關(guān)閉的回調(diào)onRemoteTerminated()、用于本地遷移發(fā)起時保存狀態(tài)數(shù)據(jù)的回調(diào)onSaveData(IntentParams saveData)和本地發(fā)起遷移的回調(diào)onStartContinuation()。
7. 請求回遷
Button btn1 = (Button) findComponentById(ResourceTable.Id_migration_button_back);
btn1.setClickedListener(new Component.ClickedListener() {
@Override
public void onClick(Component component) {
String deviceId = DeviceUtils.getDeviceId();
if(deviceId!=null){
continueAbilityReversibly(deviceId); //可撤回遷移
}
}
});
Button btn2 = (Button) findComponentById(ResourceTable.Id_migration_button_back2);
btn2.setClickedListener(new Component.ClickedListener() {
@Override
public void onClick(Component component) {
reverseContinueAbility(); //撤回遷移
}
});1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.
復(fù)制1)設(shè)備A上的Page請求回遷。
2)系統(tǒng)回調(diào)設(shè)備B上Page及其AbilitySlice棧中所有AbilitySlice實例的IAbilityContinuation.onStartContinuation()方法,以確認(rèn)當(dāng)前是否可以立即遷移。
3)如果可以立即遷移,則系統(tǒng)回調(diào)設(shè)備B上Page及其AbilitySlice棧中所有AbilitySlice實例的IAbilityContinuation.onSaveData()方法,以便保存回遷后恢復(fù)狀態(tài)必須的數(shù)據(jù)。
4)如果保存數(shù)據(jù)成功,則系統(tǒng)在設(shè)備A上Page恢復(fù)AbilitySlice棧,然后回調(diào)IAbilityContinuation.onRestoreData()方法,傳遞此前保存的數(shù)據(jù)。
5)如果數(shù)據(jù)恢復(fù)成功,則系統(tǒng)終止設(shè)備B上Page的生命周期。
編輯:hfy
-
HarmonyOS
+關(guān)注
關(guān)注
79文章
1987瀏覽量
31070
發(fā)布評論請先 登錄
相關(guān)推薦
鴻蒙OS 跨設(shè)備遷移
AKI跨語言調(diào)用庫神助攻C/C++代碼遷移至HarmonyOS NEXT
AIGC入門及鴻蒙入門
#新年新氣象,大家新年快樂!#AIGC入門及鴻蒙入門
怎么入門DevEco Studio 分布式跨設(shè)備應(yīng)用開發(fā)?
課程推薦【1】 | 鴻蒙設(shè)備開發(fā)入門
#2020征文-手機#【鴻蒙基地】鴻蒙跨設(shè)備啟動窗口:Page Ability
HarmonyOS教程—基于跨設(shè)備遷移和分布式文件能力,實現(xiàn)郵件的跨設(shè)備編輯和附件的調(diào)用
鴻蒙應(yīng)用開發(fā)入門資料合集
通過HarmonyOS分布式能力實現(xiàn)任務(wù)的跨設(shè)備遷移設(shè)計資料分享
HarmonyOS應(yīng)用開發(fā)-DiseributedVideoCodelab跨設(shè)備視頻遷移
什么是HarmonyOS“跨設(shè)備遷移”?
鴻蒙開發(fā):應(yīng)用組件跨設(shè)備交互(流轉(zhuǎn))【跨端遷移】

評論