轻松玩转HDC2021趣味闯关赛平行视界服务流转 原创 精华

狼哥Army
发布于 2021-11-3 00:08
浏览
6收藏

一, 前言

    此帖子是对参加HDC2021 Codelabs趣味闯关赛的总结,此Demo是基于Codelabs里Java电影卡片基础上开发的,添加了平行视界,服务流转功能知识点, 先说一下<HarmonyOS闯关赛> 场景: 手机上电影推荐卡片, 定期推送Top热度电影, 点击某一条影片, 跳转到影片列表页面, 点击其中一条影片可展示平行视界界面. 右侧影片详情页面可分享给家人或者朋友浏览. 功能: 开发一个电影推荐卡片, 并具有流转功能. 涉及卡片: JS电影卡片, 平行视界, 分布式邮件. 功能体验路径: 1. 开发实现一个电影展示类应用, 并具备卡片功能; 2. 点击卡片, 可跳转到电影列表页面, 点击列表中某一影片, 进入平行视界影片详情页包含电影简介, 图片, 热度, 评分; 3. 电影详情页点击流转按钮, 可流转到分布式组网内其它设备上.

    闯关赛题要求就是上面介绍的,我是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/
轻松玩转HDC2021趣味闯关赛平行视界服务流转-鸿蒙开发者社区

三, 工程搭建

     打开Codelabs网站找到Java电影卡片, 点击参考到gitee下载这个Sample的源代码, 上面也说了, 这个实例是基于Java电影卡片基础上, 加入平行视界和服务流转功能, 下载完成后, 解压出来, 打开DevEco Studio开发工具, 点击File -> Open找到刚才解压出来的MovieCardDemo电影卡片实例.

轻松玩转HDC2021趣味闯关赛平行视界服务流转-鸿蒙开发者社区

轻松玩转HDC2021趣味闯关赛平行视界服务流转-鸿蒙开发者社区

四, 新增和修改文件介绍

     先说一下项目要简单支持平行视界, 主要就是两个配置文件:
          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闯关赛原图.
轻松玩转HDC2021趣味闯关赛平行视界服务流转-鸿蒙开发者社区

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
9
收藏 6
回复
举报
4条回复
按时间正序
/
按时间倒序
红叶亦知秋
红叶亦知秋

楼主能整合出一个完整的Demo也是一份厉害的能力了。

1
回复
2021-11-3 10:55:40
狼哥Army
狼哥Army 回复了 红叶亦知秋
楼主能整合出一个完整的Demo也是一份厉害的能力了。

谢谢,夸奖

1
回复
2021-11-3 11:23:09
甜甜爱开发
甜甜爱开发

期待楼主一个新的demo,楼主挑战成功了吗?

回复
2021-11-5 10:52:00
狼哥Army
狼哥Army 回复了 甜甜爱开发
期待楼主一个新的demo,楼主挑战成功了吗?

挑战成功了,换了个AI音箱,新Demo写好了,帖子还没有时间写,新Demo的效果图上传到B站了:

https://www.bilibili.com/video/BV1tL4y1q7A6

回复
2021-11-9 17:10:58
回复
    相关推荐