流轉在 HarmonyOS 中泛指多設備分布式操作,也是 HarmonyOS 的亮點之一。
流轉按體驗可以分為跨端遷移和多端協同,這里主要跟大家講一下如何進行跨端遷移,以及我在項目開發過程中,所遇到的問題與解決方法。
具體概念這里就不做過多的贅述了,大家可以查閱官方文檔:
https://developer.harmonyos.com/cn/docs/documentation/doc-guides/hop-overview-0000001092995092
開發步驟
在開發過程中,我們可以根據業務需求分為以下兩種場景:
-
同個 FA 之間的遷移(Ability1—Ability1)
-
不同 FA 之間的遷移(Ability1—Ability2)
下面給大家介紹一下以上兩種場景的具體的開發步驟。 ①同個 FA 之間的遷移
同個 FA 之間的遷移是指不同設備端安裝了同個 FA,官方文檔已經有比較詳細的開發步驟,下面只給大家講一下需要注意的事項及我所遇到的問題避免大家踩坑。
我們在創建完一個 FA 之后,因為我們大部門的業務邏輯都是在 AbilitySlice,所以我們在 Ability 及 AbilitySlice 都要去實現 IAbilityContinuation 接口。
并且將 Ability 中實現的 onStartContinuation()、onSaveData(IntentParams intentParams)、onRestoreData(IntentParams intentParams)的返回值,都設為 true。
publicclassMainAbilityextendsAbilityimplementsIAbilityContinuation{
@Override
publicbooleanonStartContinuation(){
returntrue;
}
@Override
publicbooleanonSaveData(IntentParamsintentParams){
returntrue;
}
@Override
publicbooleanonRestoreData(IntentParamsintentParams){
returntrue;
}
//省略部分代碼
...
}
在對應的 FA 模塊的 config.json 中,配置對應的權限,且在代碼中也需要動態申請。
"reqPermissions":[
{
"name":"ohos.permission.DISTRIBUTED_DATASYNC"},
{
"name":"ohos.permission.DISTRIBUTED_DEVICE_STATE_CHANGE"},
{
"name":"ohos.permission.GET_DISTRIBUTED_DEVICE_INFO"},
{
"name":"ohos.permission.GET_BUNDLE_INFO"}
]
if(canRequestPermission(SystemPermission.DISTRIBUTED_DATASYNC)){
//是否可以申請彈框授權(首次申請或者用戶未選擇禁止且不再提示)
requestPermissionsFromUser(
newString[]{SystemPermission.DISTRIBUTED_DATASYNC},PERMISSIONS_REQUEST_DISTRIBUTED);
}
定義相關參數、設置流轉任務管理服務回調函數、注冊流轉任務管理服務、管理流轉的目標設備,同時需要在流轉結束時解注冊流轉任務管理服務。
//流轉應用包名
privateStringBUNDLE_NAME="XXX.XXX.XXX";
//注冊流轉任務管理服務后返回的Abilitytoken
privateintabilityToken;
//用戶在設備列表中選擇設備后返回的設備ID
privateStringselectDeviceId;
//獲取流轉任務管理服務管理類
privateIContinuationRegisterManagercontinuationRegisterManager;
//設置流轉任務管理服務設備狀態變更的回調
privateIContinuationDeviceCallbackcontinuationDeviceCallback=newIContinuationDeviceCallback(){
@Override
publicvoidonDeviceConnectDone(StringdeviceId,StringdeviceType){
selectDeviceId=deviceId;
continuationRegisterManager.updateConnectStatus(abilityToken,selectDeviceId,DeviceConnectState.CONNECTING.getState(),null);
...
}
@Override
publicvoidonDeviceDisconnectDone(Strings){
getUITaskDispatcher().asyncDispatch(()->{
continuationRegisterManager.updateConnectStatus(abilityToken,selectDeviceId,DeviceConnectState.DIS_CONNECTING.getState(),null);
});
unRegisterContinuation();
}
};
//設置注冊流轉任務管理服務回調
privateRequestCallbackrequestCallback=newRequestCallback(){
@Override
publicvoidonResult(intresult){
abilityToken=result;
}
};
...
@Override
publicvoidonStart(Intentintent){
...
continuationRegisterManager=getContinuationRegisterManager();
}
@Override
publicvoidonStop(){
super.onStop();
//解注冊流轉任務管理服務
continuationRegisterManager.unregister(abilityToken,null);
//斷開流轉任務管理服務連接
continuationRegisterManager.disconnect();
}
在 Api5 的時候 IContinuationDeviceCallback 的回調接口跟官方文檔有些出入,當你選擇設備后會在 onDeviceConnectDone 返回你所選擇的設備 ID 及設備類型。
注冊流轉服務之后我們便可以調起系統流轉選擇設備彈窗,可以通過 ExtraParams 對設備進行過濾,如不需要過濾,可不傳。
ExtraParamsparams=newExtraParams();
String[]devTypes=newString[]{ExtraParams.DEVICETYPE_SMART_PHONE,ExtraParams.DEVICETYPE_SMART_WATCH,ExtraParams.DEVICETYPE_SMART_PAD};
params.setDevType(devTypes);
registerContinuation();
//顯示選擇設備列表
continuationRegisterManager.showDeviceList(abilityToken,params,newRequestCallback(){
@Override
publicvoidonResult(intresult){
}
});
選擇完設備之后會通過上述的 IContinuationDeviceCallback 的 onDeviceConnectDone 方法進行回調。
之后通過 continueAbility 方法傳入目標設備的 DeviceID,將運行的 FA 遷移到目標設備,實現業務在設備間無縫遷移。
//設置流轉任務管理服務設備狀態變更的回調
privateIContinuationDeviceCallbackcontinuationDeviceCallback=newIContinuationDeviceCallback(){
@Override
publicvoidonDeviceConnectDone(StringdeviceId,StringdeviceType){
selectDeviceId=deviceId;
getUITaskDispatcher().asyncDispatch(()->{
continuationRegisterManager.updateConnectStatus(abilityToken,selectDeviceId,DeviceConnectState.CONNECTING.getState(),null);
});
if(selectDeviceId!=null){
continueAbility(selectDeviceId);
}
...
}
@Override
publicvoidonDeviceDisconnectDone(Strings){
...
unRegisterContinuation();
}
};
在 FA 遷移中我覺得最主要的部分就是狀態和數據的傳遞,要讓用戶體驗到”無縫“的用戶體驗,需要通過實現 IAbilityContinuation 接口來實現數據的傳遞。
主要代碼如下:
@Override
publicbooleanonSaveData(IntentParamssaveData){
//根據業務需求,在這里去設置需要傳遞的數據
saveData.setParam("continueParam",continueParam);
returntrue;
}
@Override
publicbooleanonRestoreData(IntentParamsrestoreData){
//遠端FA遷移傳來的狀態數據,開發者可以按照自身業務對這些數據進行處理
Objectdata=restoreData.getParam("continueParam");
getUITaskDispatcher().asyncDispatch(()->{
});
returntrue;
}
需要注意的是,在 onRestoreData 處理數據更新 UI 的時候,需要在 UI 線程中去更新,否則會報錯。 ②不同 FA 之間的遷移 在實際開發中可能會因為設備端的部分需求、UI 的不同,例如車機、手機、手表,從而開發了不同的 FA。
不同 FA 之間的遷移幾乎與同個 FA 之間遷移配置一致,只是我們的 AbilitySlice 不需要再實現 IAbilityContinuation 接口來實現數據的同步,而是通過 Intent,具體實現如下。
首先我們先在選擇設備成功后的回調 IContinuationDeviceCallback 初始化分布式環境。
//設置流轉任務管理服務設備狀態變更的回調
privateIContinuationDeviceCallbackcontinuationDeviceCallback=newIContinuationDeviceCallback(){
@Override
publicvoidonDeviceConnectDone(StringdeviceId,StringdeviceType){
selectDeviceId=deviceId;
//省略部分代碼
...
try{
//初始化分布式環境
DeviceManager.initDistributedEnvironment(selectDeviceId,newIInitCallback(){
@Override
publicvoidonInitSuccess(Stringsuccess){
}
@Override
publicvoidonInitFailure(Stringfailure,intresult){
}
});
}catch(RemoteExceptione){
e.printStackTrace();
}
...
}
....
};
之前我們是通過 continueAbility() 方法進行跳轉,而現在我們需要通過 Intent 方法進行跳轉。
Intentintent=newIntent();
Operationoperation=newIntent.OperationBuilder()
.withDeviceId(deviceId)
.withBundleName(bundleName)
.withAbilityName(abilityName)
.withFlags(Intent.FLAG_ABILITYSLICE_MULTI_DEVICE)
.build();
intent.setOperation(operation);
IntentParamsintentParams=newIntentParams();
//通過IntentParams傳遞參數
...
startAbility(intent);
在接收方,我們可以通過 onStart(Intent intent) 方法接受傳遞過來的參數,再根據自己的業務邏輯實現數據同步。 ③自定義設備選擇彈窗 在實際項目開發中我們也可以自定義流轉彈窗樣式,但并不推薦這種方式,經測試發現只有在兩個設備通過藍牙連接的時候才能獲取到設備列表,只有在特定的場景。
例如手機與車機、手機與手表在實際使用過程中我們基本上是會保持藍牙連接的,通過這種方式實現流轉會更穩定。但如果不能保持藍牙實時連接的場景則不推薦。
官方 API提供了 DeviceManager.getDeviceList() 來獲取遠端設備,具體代碼如下。
publicstaticListgetDeviceList(){
//調用DeviceManager的getDeviceList接口,通過FLAG_GET_ONLINE_DEVICE標記獲得在線設備列表
ListonlineDevices=DeviceManager.getDeviceList(DeviceInfo.FLAG_GET_ONLINE_DEVICE);
//判斷組網設備是否為空
if(onlineDevices==null){
LogUtil.e(TAG,"onlinedevicesisnull");
returnnewArrayList<>();
}
returnonlineDevices;
}
獲取到設備列表后,我們就可以自行實現頁面了,在上述的 showDeviceList() 彈出設備列表的位置替換成自己的彈窗即可。
結語
目前在 DevEco Studio 2.1 Release 以上版本已經支持跨端遷移的模擬器了。
如果沒有顯示出來可以在 Settings-DevEco Labs 勾選 Enable Super Device。
以上過程是在實際開發過程中慢慢摸索得出,如有不對的地方,歡迎在評論區指出,共同探討(附下載)。
https://harmonyos.51cto.com/posts/9013
-
鴻蒙系統
+關注
關注
183文章
2634瀏覽量
66305 -
HarmonyOS
+關注
關注
79文章
1973瀏覽量
30143
原文標題:HarmonyOS流轉,替你踩坑了!!!
文章出處:【微信號:gh_834c4b3d87fe,微信公眾號:OpenHarmony技術社區】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論