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

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

四, 新增和修改文件介紹
先說一下項(xiàng)目要簡單支持平行視界, 主要就是兩個(gè)配置文件:
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"
- }
- }
- }
- ]
- }
設(shè)備選擇對話框DeviceDialog是封裝好的一個(gè)類, 來自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;
- // 獲取流轉(zhuǎn)任務(wù)管理服務(wù)管理類
- 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;
- // 設(shè)置流轉(zhuǎn)任務(wù)管理服務(wù)設(shè)備狀態(tài)變更的回調(diào)
- 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) {
- }
- };
- // 設(shè)置注冊流轉(zhuǎn)任務(wù)管理服務(wù)回調(diào)
- 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();
- }
- // 注冊流轉(zhuǎn)任務(wù)管理服務(wù)管理類
- 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);
- }
- /**
- * 打開設(shè)備選擇框
- *
- * @since 2021-09-10
- */
- public void showDeviceList() {
- // 設(shè)置過濾設(shè)備類型
- 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);
- // 顯示選擇設(shè)備列表
- continuationRegisterManager.showDeviceList(abilityToken, params, null);
- }
- // Return the device ID
- private void returnDeviceId() {
- HiLog.info(LABEL_LOG, "deviceid::" + selectDeviceId);
- MoviesDetailAbilitySlice.setDeviceId(selectDeviceId);
- }
- /**
- * 斷開流轉(zhuǎn)任務(wù)管理服務(wù)
- *
- * @since 2021-09-10
- */
- public void clearRegisterManager() {
- // 解注冊流轉(zhuǎn)任務(wù)管理服務(wù)
- continuationRegisterManager.unregister(abilityToken, null);
- // 斷開流轉(zhuǎn)任務(wù)管理服務(wù)連接
- 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();
- }
下來說一下關(guān)于服務(wù)流轉(zhuǎn)的代碼, MoviesDetailAbility和MoviesDetailAbilitySlice都實(shí)現(xiàn)IAbilityContinuation接口, 并且實(shí)現(xiàn)接口里的方法:
- 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;
- }
- }
要實(shí)現(xiàn)服務(wù)流轉(zhuǎn), 首先要在config.json權(quán)限申請, 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"
- }
- }
- ]
同時(shí)也在應(yīng)用入口提供顯示權(quán)限申請:
- @Override
- public void onStart(Intent intent) {
- super.onStart(intent);
- super.setMainRoute(MainAbilitySlice.class.getName());
- // 聲明跨端遷移訪問的權(quán)限
- requestPermissionsFromUser(new String[]{"ohos.permission.DISTRIBUTED_DATASYNC"}, 0);
- addActionRoute(ACTION_DETAIL, MoviesDetailAbilitySlice.class.getName());
- initData();
- initMyHandler();
- }
到此就介紹完了, 大家是不是感覺到, 我就是一個(gè)搬運(yùn)工, 在不同的Sample上, 合并成為一個(gè), 這個(gè)Demo確實(shí)是這樣, 把不同的知識點(diǎn)集合在一起, 形成一個(gè)符合要求的應(yīng)用, 下來我打算再寫一個(gè)一樣需求的應(yīng)用, 但是從創(chuàng)建空白項(xiàng)目開始, 把列表顯示, 詳情, 服務(wù)卡片, 平行視界, 服務(wù)流轉(zhuǎn)體驗(yàn)出來, 大家有空也一起根據(jù)需求擼出來吧!!! 下面圖片是當(dāng)時(shí)HDC2021 Codelabs闖關(guān)賽原圖。
51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)