輕松玩轉HDC2021趣味闖關賽平行視界服務流轉
一, 前言
此帖子是對參加HDC2021 Codelabs趣味闖關賽的總結,此Demo是基于Codelabs里Java電影卡片基礎上開發的,添加了平行視界,服務流轉功能知識點, 先說一下。
闖關賽題要求就是上面介紹的,我是24號才去參加Codelabs挑戰賽的, 23號一直呆在Harmony應用與服務開發教室聽課, 晚上聽到參加了Codelabs挑戰賽的小伙伴說, 闖關賽有些難度,特別是平行視界功能,之前沒有接觸過,23號時小伙伴也沒有完成闖關賽,音樂會結束后我們回到酒店,打開電腦來研究起來,我開始是過了一遍Codelabs的平行視界Sample, 然后按照小伙伴說的,先弄一個電影服務卡片,然后點擊卡片進到電影列表,點擊電影列表某一項,平行視界顯示詳情,在詳情頁可以流轉. 說到服務卡片, 我們都知道用JS來寫比較快,要簡單些, 由于我們的目的是要弄懂平行視界, 就直接用了Codelabs里的JS電影卡片,想加上平行視界, 看了N遍平行視界Sample, 修改了多次JS電影卡片,最終還是不能實現平行視界,當時已經是零晨3點多了,我和小伙伴說,看來今晚我們搞不定了,會不會是平視視界不支持JS Ability的, 先睡覺了. 第二天到了Codelabs挑戰現場問了一下平行視界支持JS界面嗎? 說不行,目前只支持Java的,無語了. 其實實現簡單的平行視界, 也就是兩個配置文件,一行Java代碼都不用寫, 首先配置一下config.json文件, 然后添加easygo.json文件,配置一下左邊顯示哪個Ability, 右邊顯示哪個Ability就可以了,下面來簡單介紹一下開發過程。
二, 實現效果
B站視頻:https://www.bilibili.com/video/BV1N34y1Z7Gj/

三, 工程搭建
打開Codelabs網站找到Java電影卡片, 點擊參考到gitee下載這個Sample的源代碼, 上面也說了, 這個實例是基于Java電影卡片基礎上, 加入平行視界和服務流轉功能, 下載完成后, 解壓出來, 打開DevEco Studio開發工具, 點擊File -> Open找到剛才解壓出來的MovieCardDemo電影卡片實例。

四, 新增和修改文件介紹
先說一下項目要簡單支持平行視界, 主要就是兩個配置文件:
1. config.json配置支持平行視界, 在module下添加:
- "metaData": {
- "customizeData": [
- {
- "name": "EasyGoClient",
- "value": "true"
- }
- ]
- }
2. 添加easygo.json文件支持平行視界:
- {
- "easyGoVersion": "1.0",
- "client": "com.army.study", // 與config.json文件的bundleName一致
- "logicEntities": [
- {
- "head": {
- "function": "magicwindow",
- "required": "true"
- },
- "body": {
- "mode": "1",
- "abilityPairs": [
- {
- "from": "com.huawei.cookbook.MainAbility", // 顯示在平行視界左邊頁面
- "to": "com.huawei.cookbook.MoviesDetailAbility" // 顯示在平行視界右邊頁面
- }
- ],
- "UX": {
- "isDraggable": "true",
- "supportRotationUxCompat": "true",
- "supportDraggingToFullScreen": "ALL"
- }
- }
- }
- ]
- }
設備選擇對話框DeviceDialog是封裝好的一個類, 來自Codelabs平行視界代碼里。
- package com.huawei.cookbook;
- import com.huawei.cookbook.slice.MoviesDetailAbilitySlice;
- import ohos.aafwk.ability.continuation.*;
- import ohos.app.Context;
- import ohos.hiviewdfx.HiLog;
- import ohos.hiviewdfx.HiLogLabel;
- public class DeviceDialog {
- private static final HiLogLabel LABEL_LOG = new HiLogLabel(3, 0xD001100, "chuangguan");
- // context Object
- private final Context context;
- // 獲取流轉任務管理服務管理類
- private final IContinuationRegisterManager continuationRegisterManager;
- // Ability token returned after the transfer task management service is registered
- private int abilityToken;
- // Device ID returned after a user selects a device in the device list
- private String selectDeviceId;
- // 設置流轉任務管理服務設備狀態變更的回調
- private final IContinuationDeviceCallback callback = new IContinuationDeviceCallback() {
- @Override
- public void onDeviceConnectDone(String str, String str1) {
- // Set the device ID after the user selects the device
- selectDeviceId = str;
- continuationRegisterManager.updateConnectStatus(abilityToken, selectDeviceId,
- DeviceConnectState.CONNECTED.getState(), null);
- returnDeviceId();
- }
- @Override
- public void onDeviceDisconnectDone(String str) {
- }
- };
- // 設置注冊流轉任務管理服務回調
- private final RequestCallback requestCallback = new RequestCallback() {
- @Override
- public void onResult(int result) {
- abilityToken = result;
- }
- };
- /**
- * Initialize the DeviceDialog, set the transfer task management service management class,
- * and register the transfer task management service management class.
- *
- * @param continuationRegisterManager continuationRegisterManager
- * @param slice slice
- * @since 2021-09-10
- */
- public DeviceDialog(IContinuationRegisterManager continuationRegisterManager, Context slice) {
- this.continuationRegisterManager = continuationRegisterManager;
- this.context = slice;
- // 注冊
- registerManager();
- }
- // 注冊流轉任務管理服務管理類
- private void registerManager() {
- // 增加過濾條件
- ExtraParams params = new ExtraParams();
- String[] devTypes = new String[]{ExtraParams.DEVICETYPE_SMART_PAD, ExtraParams.DEVICETYPE_SMART_PHONE};
- params.setDevType(devTypes);
- continuationRegisterManager.register(context.getBundleName(), params, callback, requestCallback);
- }
- /**
- * 打開設備選擇框
- *
- * @since 2021-09-10
- */
- public void showDeviceList() {
- // 設置過濾設備類型
- ExtraParams params = new ExtraParams();
- String[] devTypes = new String[]{ExtraParams.DEVICETYPE_SMART_PAD, ExtraParams.DEVICETYPE_SMART_PHONE};
- params.setDevType(devTypes);
- // 注冊
- continuationRegisterManager.register(context.getBundleName(), params, callback, requestCallback);
- // 顯示選擇設備列表
- continuationRegisterManager.showDeviceList(abilityToken, params, null);
- }
- // Return the device ID
- private void returnDeviceId() {
- HiLog.info(LABEL_LOG, "deviceid::" + selectDeviceId);
- MoviesDetailAbilitySlice.setDeviceId(selectDeviceId);
- }
- /**
- * 斷開流轉任務管理服務
- *
- * @since 2021-09-10
- */
- public void clearRegisterManager() {
- // 解注冊流轉任務管理服務
- continuationRegisterManager.unregister(abilityToken, null);
- // 斷開流轉任務管理服務連接
- continuationRegisterManager.disconnect();
- }
- }
提示對話框Utils公共類:
- public static void creatToastDialog(Context context, String message) {
- Component component = LayoutScatter.getInstance(context)
- .parse(ResourceTable.Layout_layout_toast, null, false);
- Component componentText = component.findComponentById(ResourceTable.Id_msg_toast);
- if (componentText instanceof Text) {
- ((Text) componentText).setText(message);
- }
- new ToastDialog(context)
- .setComponent(component)
- .setSize(DirectionalLayout.LayoutConfig.MATCH_CONTENT, DirectionalLayout.LayoutConfig.MATCH_CONTENT)
- .setAlignment(LayoutAlignment.CENTER).show();
- }
下來說一下關于服務流轉的代碼, MoviesDetailAbility和MoviesDetailAbilitySlice都實現IAbilityContinuation接口, 并且實現接口里的方法:
- public class MoviesDetailAbility extends Ability implements IAbilityContinuation {
- @Override
- public void onStart(Intent intent) {
- super.onStart(intent);
- super.setMainRoute(MoviesDetailAbilitySlice.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) {
- }
- }
- public class MoviesDetailAbilitySlice extends AbilitySlice implements IAbilityContinuation {
- // 此處省略原來的代碼
- @Override
- public boolean onStartContinuation() {
- return true;
- }
- @Override
- public boolean onSaveData(IntentParams saveData) {
- saveData.setParam("remoteMovieId", movieId);
- return true;
- }
- @Override
- public boolean onRestoreData(IntentParams restoreData) {
- this.movieId = Long.parseLong(restoreData.getParam("remoteMovieId").toString());
- return true;
- }
- @Override
- public void onCompleteContinuation(int i) {
- isCirculation = false;
- }
- }
要實現服務流轉, 首先要在config.json權限申請, module下添加:
- "reqPermissions": [
- {
- "name": "ohos.permission.DISTRIBUTED_DATASYNC",
- "reason": "$string:entry_MoviesDetailAbility",
- "usedScene":
- {
- "ability": [
- "com.huawei.cookbook.MainAbility",
- "com.huawei.cookbook.MoviesDetailAbility"
- ],
- "when": "always"
- }
- },
- {
- "name": "ohos.permission.GET_DISTRIBUTED_DEVICE_INFO",
- "reason": "$string:entry_MoviesDetailAbility",
- "usedScene":
- {
- "ability": [
- "com.huawei.cookbook.MainAbility",
- "com.huawei.cookbook.MoviesDetailAbility"
- ],
- "when": "always"
- }
- }
- ]
同時也在應用入口提供顯示權限申請:
- @Override
- public void onStart(Intent intent) {
- super.onStart(intent);
- super.setMainRoute(MainAbilitySlice.class.getName());
- // 聲明跨端遷移訪問的權限
- requestPermissionsFromUser(new String[]{"ohos.permission.DISTRIBUTED_DATASYNC"}, 0);
- addActionRoute(ACTION_DETAIL, MoviesDetailAbilitySlice.class.getName());
- initData();
- initMyHandler();
- }
到此就介紹完了, 大家是不是感覺到, 我就是一個搬運工, 在不同的Sample上, 合并成為一個, 這個Demo確實是這樣, 把不同的知識點集合在一起, 形成一個符合要求的應用, 下來我打算再寫一個一樣需求的應用, 但是從創建空白項目開始, 把列表顯示, 詳情, 服務卡片, 平行視界, 服務流轉體驗出來, 大家有空也一起根據需求擼出來吧!!! 下面圖片是當時HDC2021 Codelabs闖關賽原圖。