手把手教HDC2021趣味闯关赛平行视界服务流转 原创 精华

发布于 2021-11-9 18:42
浏览
6收藏

一, 前言

上一篇 轻松玩转HDC2021趣味闯关赛平行视界服务流转 帖子里是基于Codelabs里Java电影卡片,平行视界Sample集成的,此帖从空白项目开始,一步步教你如何在项目里,学到列表显示,平行视界,服务卡片,服务流转各知识点。下面大慨说一下项目的开发流程:

  1. 实现List显示, 点击某项跳转到RightAbility界面
  2. 添加JS服务卡片, 点击跳转到List列表
  3. 平行视界, 点击List列表, 左边显示列表,右边显示详情图片
  4. 服务流转, 在详情,点击连接图标, 选择流转设备; 再点击流转图标==

二, 实现效果
    B站视频:https://www.bilibili.com/video/BV1tL4y1q7A6/
手把手教HDC2021趣味闯关赛平行视界服务流转-开源基础软件社区

三, 工程搭建
    打开DevEco Studio 3.0.0.600开发工具, 点击菜单File -> New -> New Project, 弹出以下框,按截图选择创建:
手把手教HDC2021趣味闯关赛平行视界服务流转-开源基础软件社区

    下一步后的界面以下,请按照标注操作。
手把手教HDC2021趣味闯关赛平行视界服务流转-开源基础软件社区

    空模板项目到此,就创建完成了,下面我们来按照上面说的步骤一步一步来完成。

四, 工程讲解

    1. 实现List显示, 点击某项跳转到RightAbility界面

        首先把List列表显示出来,下面是List列表的XML布局文件,由于List列表项是数据驱动的,这里只提供List容器,并给予id就可以。

<?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:alignment="center"
    ohos:orientation="vertical">
    <ListContainer
        ohos:id="$+id:list"
        ohos:height="match_parent"
        ohos:width="match_parent"
        ohos:orientation="vertical"/>
</DirectionalLayout>

        从上面效果图可以看出,列表项左边显示图片,右边显示文字,下面有一条分割线,XML布局文件以下:

<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayout
    xmlns:ohos="http://schemas.huawei.com/res/ohos"
    ohos:height="match_content"
    ohos:width="match_parent"
    ohos:orientation="vertical">
    <DirectionalLayout
        ohos:height="100vp"
        ohos:width="match_parent"
        ohos:padding="10vp"
        ohos:orientation="horizontal">
        <Image
            ohos:id="$+id:img"
            ohos:height="match_parent"
            ohos:scale_mode="zoom_center"
            ohos:width="120vp"></Image>
        <Text
            ohos:id="$+id:title"
            ohos:height="match_parent"
            ohos:width="match_content"
            ohos:padding="5vp"
            ohos:text_size="16fp"
            ohos:left_margin="10vp"/>
    </DirectionalLayout>
    <Component
        ohos:height="1vp"
        ohos:width="match_parent"
        ohos:background_element="#CCCCCC"/>
</DirectionalLayout>

        List列表的页面布局就说完了,下面来说一下Java代码:先介绍一下列表项的实体类,也就两个属性,一个是图片,一个是标题

import ohos.media.image.PixelMap;

public class Item {
    // 显示图片
    private PixelMap img;
    // 显示每项标题
    private String title;

    public PixelMap getImg() {
        return img;
    }
    public void setImg(PixelMap img) {
        this.img = img;
    }
    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
}

        下面介绍一下List列表的核心部分就是适配器类的实现:大部分代码都有注释,适配器类首先要继承BaseItemProvider 基础类,然后实现里面相应的方法。

/**
 * 列表适配器类
 */
public class ListAdapter extends BaseItemProvider {

    // 上下文
    private static Context context;
    // 数据项列表
    private List<Item> items;
    // 自定义事件处理
    private MyEventHandle myEventHandle;


    /**
     * 构造方法
     * @param items
     * @param context
     */
    public ListAdapter(List<Item> items, Context context) {
        this.items = items == null ? new ArrayList() : items;
        this.context = context;
    }
    /**
     * 获取列表有多少项
     * @return
     */
    @Override
    public int getCount() {
        return items == null ? 0 : items.size();
    }
    /**
     * 获取当前项数据
     * @param i
     * @return
     */
    @Override
    public Item getItem(int i) {
        return this.items.get(i);
    }
    /**
     * 获取当前Id
     * @param i
     * @return
     */
    @Override
    public long getItemId(int i) {
        return i;
    }
    /**
     * 获取组件内容
     * @param i
     * @param component
     * @param componentContainer
     * @return
     */
    @Override
    public Component getComponent(int i, Component component, ComponentContainer componentContainer) {
        ViewHolder viewHolder = null;
        Component cmp = component;
        if (cmp == null) {
            cmp = LayoutScatter.getInstance(context).parse(ResourceTable.Layout_item, null, false);
            // 初始化项布局
            viewHolder = new ViewHolder();
            // 获取图片组件
            viewHolder.img = (Image)cmp.findComponentById(ResourceTable.Id_img);
            // 获取标题组件
            viewHolder.title = (Text)cmp.findComponentById(ResourceTable.Id_title);
            // 缓存起来
            cmp.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder) cmp.getTag();
        }

        viewHolder.img.setPixelMap(items.get(i).getImg());
        viewHolder.title.setText(items.get(i).getTitle());
        viewHolder.img.setClickedListener(listener -> itemClick(i));
        viewHolder.title.setClickedListener(listener -> itemClick(i));

        return cmp;
    }
    public void replace(Collection<Item> listConstructor) {
        if (listConstructor == null) {
            return;
        }
        this.items = null;
        // 重新初始化listContainer中的数据
        this.items = new ArrayList<>(0);
        // 将重新得到的项数据放到listContainer中
        this.items.addAll(listConstructor);
        // 刷新listContainer,调用getComponent方法重新设置页面元素布局
        notifyDataChanged();
    }
    /**
     * 内部类,封装列表项组件
     */
    private static class ViewHolder {
        // 显示图片
        Image img;
        // 显示标题
        Text title;
    }
    /**
     * 点击图片或标题事件
     * @param index
     */
    private void itemClick(int index) {
        // 初始化处理程序
        initHandler();
        // 获取内部事件
        InnerEvent event = InnerEvent.get(1, 0, index);
        myEventHandle.sendEvent(event);
    }
    /**
     * 初始化处理程序
     */
    private void initHandler() {
        EventRunner runner = EventRunner.getMainEventRunner();
        if (runner == null) {
            return;
        }
        myEventHandle = new MyEventHandle(runner);
    }
    /**
     * 自定义处理事件
     */
    public static class MyEventHandle extends EventHandler {
        MyEventHandle(EventRunner runner) throws IllegalArgumentException {
            super(runner);
        }

        @Override
        protected void processEvent(InnerEvent event) {
            super.processEvent(event);
            int eventId = event.eventId;
            int index = (Integer) event.object;
            if (eventId == 1) {
                IntentParams intentParams = new IntentParams();
                intentParams.setParam("index", index); // 选择列表项下标
                // 跳转到 RightAbility 分屏
                Intent intent = new Intent();
                intent.setParams(intentParams);
                ElementName element = new ElementName("", context.getBundleName(), RightAbility.class.getName());
                intent.setElement(element);
                context.startAbility(intent, 0);
            }
        }
    }
}

        项目用的数据是静态数据,在一个Utils封装好的,以下:

public class Utils {
    private static final HiLogLabel TAG = new HiLogLabel(HiLog.LOG_APP, 0xD001400, "Utils");

    private static final List<Integer> PICTURE_IDS = Arrays.asList(ResourceTable.Media_1,
            ResourceTable.Media_2, ResourceTable.Media_3,
            ResourceTable.Media_4, ResourceTable.Media_5,
            ResourceTable.Media_6, ResourceTable.Media_7,
            ResourceTable.Media_8, ResourceTable.Media_9,
            ResourceTable.Media_10);

    private static List<PixelMap> resourcePixelMaps;

    public static void transResourceIdsToListOnce(Context context) {
        resourcePixelMaps = new ArrayList<>(0);
        // Set the pixel map
        for (int index: PICTURE_IDS) {
            InputStream source = null;
            ImageSource imageSource;
            try {
                source = context.getResourceManager().getResource(index);
                imageSource = ImageSource.create(source, null);
                resourcePixelMaps.add(imageSource.createPixelmap(null));
            } catch (IOException | NotExistException e) {
                HiLog.error(TAG, "Get Resource PixelMap error");
            } finally {
                try {
                    assert source != null;
                    source.close();
                } catch (IOException e) {
                    HiLog.error(TAG, "getPixelMap source close error");
                }
            }
        }
    }

    /**
     * 封装列表项数据
     * @return
     */
    public static List<Item> getItems() {
        List<Item> items = new ArrayList<>();

        int index = 1;
        for (PixelMap pixelMap : resourcePixelMaps) {
            Item item = new Item();
            item.setImg(pixelMap);
            item.setTitle("测试标题 " + index);
            items.add(item);
            index++;
        }

        return items;
    }

    /**
     * 根据下标获取列表项数据
     * @param index
     * @return
     */
    public static Item getItem(int index) {
        List<Item> items = getItems();
        return items.get(index);
    }
}

        在MainAbilitySlice加载显示出列表容器里的内容:

public class MainAbilitySlice extends AbilitySlice {

    // 列表容器
    private static ListContainer listContainer;
    // 列表适配器类
    private static ListAdapter listAdapter;
    // 上下文
    private static Context context;


    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_main);
        context = getContext();

        // 初始化界面
        initView();
        // 将 Media 中的图像转换为 List<PixelMap>。 使用默认大小
        Utils.transResourceIdsToListOnce(context);
        // UI线程更新列表数据
        getUITaskDispatcher().delayDispatch(() -> initData(Utils.getItems()), 10);
    }
    /**
     * 初始化界面
     */
    private void initView() {
        // 获取List容器
        listContainer = (ListContainer) findComponentById(ResourceTable.Id_list);
        // 初始化列表适配器
        listAdapter = new ListAdapter(null, context);
        // 设置列表容器项数据提供者
        listContainer.setItemProvider(listAdapter);

    }
    /**
     * 更新界面数据
     * @param items
     */
    public static void initData(List<Item> items) {
        context.getUITaskDispatcher().asyncDispatch(() -> {
            listContainer.setItemProvider(listAdapter);
            listAdapter.replace(items);
        });
    }
}

这样主界面的List列表就完成了,项目用的素材图片是放在resources -> media下的,下来介绍一下点击列表项跳转到详情页面,这里我们要创建一个Page Ability, 取名为RightAbility,同时在使用平行视界时,这个Ability显示在平板的右边。
手把手教HDC2021趣味闯关赛平行视界服务流转-开源基础软件社区

界面布局分为上下显示,上面显示标题和后面用到的服务流转图标,下面显示点击的图片

<?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:alignment="center"
    ohos:orientation="vertical">
    <DependentLayout
        ohos:id="$+id:container_title"
        ohos:height="50vp"
        ohos:padding="10vp"
        ohos:width="match_parent">
        <Text
            ohos:id="$+id:right_title"
            ohos:height="match_parent"
            ohos:width="match_content"
            ohos:padding="5vp"
            ohos:text_size="16fp"
            ohos:left_margin="10vp"/>
        <Image
            ohos:id="$+id:imgConnect"
            ohos:left_margin="10vp"
            ohos:right_margin="10vp"
            ohos:height="30vp"
            ohos:width="30vp"
            ohos:background_element="$media:connect"
            ohos:left_of="$id:imgCirculation"/>
        <Image
            ohos:id="$+id:imgCirculation"
            ohos:height="30vp"
            ohos:width="30vp"
            ohos:right_margin="10vp"
            ohos:background_element="$media:circulation"
            ohos:align_parent_right="true"/>
    </DependentLayout>
    <Image
        ohos:id="$+id:right_img"
        ohos:height="match_parent"
        ohos:scale_mode="zoom_center"
        ohos:width="match_parent"></Image>
</DirectionalLayout>

在新Page Ability接收到跳转过来的参数,显示相应的标题和图片

public class RightAbilitySlice extends AbilitySlice {

    private static Context context;         // 上下文
    private static int paramIndex;          // 页面跳转参数


    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_right);
        context = getContext();

        // 如果页面跳转参数index为空, 默认为0
        paramIndex = intent.getIntParam("index", 0);
        Item item = Utils.getItem(paramIndex);

        // 初始化界面
        initView(item);
      
    }
    private void initView(Item item) {
        Image img = (Image)findComponentById(ResourceTable.Id_right_img);
        img.setPixelMap(item.getImg());

        Text title = (Text)findComponentById(ResourceTable.Id_right_title);
        title.setText(item.getTitle());

        Image btnSelect = (Image)findComponentById(ResourceTable.Id_imgConnect);
        Image btnShare = (Image)findComponentById(ResourceTable.Id_imgCirculation);

        btnSelect.setClickedListener(va -> {
            // 打开设备选择框(连接)
            //deviceDialog.showDeviceList();
        });
        btnShare.setClickedListener(va -> {
            // 流转
            //circulation();
        });
    }
}
  1. 添加JS服务卡片, 点击跳转到List列表

先创建一个JS服务卡片,步骤以下:
手把手教HDC2021趣味闯关赛平行视界服务流转-开源基础软件社区
手把手教HDC2021趣味闯关赛平行视界服务流转-开源基础软件社区
手把手教HDC2021趣味闯关赛平行视界服务流转-开源基础软件社区
默认服务卡片里面内容,不是我要的效果,我简单修改一下后:

<div class="card_root_layout">
    <div class="button_containers">
        <div class="item_first_container">
            <div class="button_left">
                <image src="/common/images/1.jpg" onclick="routerEvent"></image>
            </div>
            <div class="button_right">
                <image src="/common/images/2.jpg" onclick="routerEvent"></image>
            </div>
        </div>
        <div class="item_second_container">
            <div class="button_left">
                <image src="/common/images/3.jpg" onclick="routerEvent"></image>
            </div>
            <div class="button_right">
                <image src="/common/images/4.jpg" onclick="routerEvent"></image>
            </div>
        </div>
    </div>
</div>
.card_root_layout {
    flex-direction: column;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 100%;
    padding: 10px;
    background-color: #FFFFFF;
}
.button_containers {
    flex-direction: column;
    align-items: center;
    justify-content: center;
}
.item_first_container {
    flex-weight: 0.4;
    flex-direction: row;
    align-items: center;
    justify-content: center;
}
.item_second_container {
    flex-weight: 0.4;
    flex-direction: row;
    align-items: center;
    justify-content: center;
}
.button_left {
    flex-weight: 0.5;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 4px;
}
.button_right {
    flex-weight: 0.5;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 4px;
}

{
  "actions": {
    "routerEvent": {
      "action": "router",
      "abilityName": "com.army.study.MainAbility"
    }
  }
}

简单的服务卡片就修改好了,点击服务卡片,跳转到List列表界面。

  1. 平行视界, 点击List列表, 左边显示列表,右边显示详情图片

实现平行视界,注意三点就可以了,第一点,平行视界目前只能在两个Java Page Ability实现,第二点在resources -> rawfile目录下添加一个文件easygo.json, 第三点修改config.json配置,就可以了,下面我们就一点一点来完成平行视界效果.

第一点:上面已经创建好两个Java Page Ability了,一个是MainAbility, 一个是RightAbility。

第二点:添加easygo.json内容为

{
  "easyGoVersion": "1.0",
  "client": "com.army.study",  // 保持和config.json bundleName一致
  "logicEntities": [
    {
      "head": {
        "function": "magicwindow",
        "required": "true"
      },
      "body": {
        "mode": "1",
        "abilityPairs": [
          {
            "from": "com.army.study.MainAbility",  // 显示在平行视界左边的列表页面
            "to": "com.army.study.RightAbility"    // 显示在平行视界右边的详情页面
          }
        ],

        "UX": {
          "isDraggable": "true",
          "supportRotationUxCompat": "true",
          "supportDraggingToFullScreen": "ALL"
        }
      }
    }
  ]
}

第三点:修改config.json在moudle节点下添加以下:

    "metaData": {
      "customizeData": [
        {
          "name": "EasyGoClient",
          "value": "true"
        }
      ]
    }

平行视界效果就完成了。

  1. 服务流转, 在详情,点击连接图标, 选择流转设备; 再点击流转图标

    服务流转也是有几点注意的,第一点当然就是授权了,除了在config.json配置了权限申请,还要在应用入口加上动态授权,第二点就是实现流转的Abitily和AbilitySlic都要实现IAbilityContinuation接口,第三点就是显示当然环境下,在线设备可以流转到的设备,这里使用到了Codelabs平行视界Sample里封装好的DeviceDialog类,里面使用的流转任务管理服务管理类IContinuationRegisterManager, 简化了很多代码。下面就开始一 一介绍吧。
    

第一点授权,在config.json里module节点下添加以下配置

"reqPermissions": [
      {
        "name": "ohos.permission.DISTRIBUTED_DATASYNC",
        "usedScene":
        {
          "ability": [
            "com.army.study.MainAbility",
            "com.army.study.RightAbility"
          ],
          "when": "always"
        }
      },
      {
        "name": "ohos.permission.GET_DISTRIBUTED_DEVICE_INFO",
        "usedScene":
        {
          "ability": [
            "com.army.study.MainAbility",
            "com.army.study.RightAbility"
          ],
          "when": "always"
        }
      }
    ]

在应用入口MainAbility里onStart()方法添加动态授权:

// 声明跨端迁移访问的权限
requestPermissionsFromUser(new String[]{SystemPermission.DISTRIBUTED_DATASYNC}, 0);

第二点在RightAbility和RightAbilitySlice多实现IAbilityContinuation接口,其实RightAbility实现接口后,在实现方法里面返回true就可以,具体逻辑是在RightAbilitySlice中实现。

public class RightAbility extends Ability implements IAbilityContinuation {
    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setMainRoute(RightAbilitySlice.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 RightAbilitySlice extends AbilitySlice implements IAbilityContinuation {

    private boolean isCirculation = false;  // 是否流转中
    private static String selectDeviceId;   // 选择的设备id
    private DeviceDialog deviceDialog;      // 设备选择

    private static Context context;         // 上下文
    private static int paramIndex;          // 页面跳转参数
    private static int removeIndex;         // 流转参数

    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_right);
        context = getContext();

        // 如果页面跳转参数index为空,说明是流转过来参数, 使用流转removeIndex
        paramIndex = intent.getIntParam("index", removeIndex);
        Item item = Utils.getItem(paramIndex);

        // 初始化界面
        initView(item);
        // 初始化设备选择
        deviceDialog = new DeviceDialog(getContinuationRegisterManager(),RightAbilitySlice.this);
    }
    private void initView(Item item) {
        Image img = (Image)findComponentById(ResourceTable.Id_right_img);
        img.setPixelMap(item.getImg());

        Text title = (Text)findComponentById(ResourceTable.Id_right_title);
        title.setText(item.getTitle());

        Image btnSelect = (Image)findComponentById(ResourceTable.Id_imgConnect);
        Image btnShare = (Image)findComponentById(ResourceTable.Id_imgCirculation);

        btnSelect.setClickedListener(va -> {
            // 打开设备选择框(连接)
            deviceDialog.showDeviceList();
        });
        btnShare.setClickedListener(va -> {
            // 流转
            circulation();
        });
    }
    /**
     * 流转
     */
    private void circulation() {
        if (isCirculation) {
            Utils.createToastDialog(context, "正在流转,请稍后再试!");
            return;
        }
        if (selectDeviceId == null || "".equals(selectDeviceId)) {
            // 选择设备以后才能流转(迁移)
            Utils.createToastDialog(context, "请选择连接设备后进行流转操作!");
            return;
        }
        isCirculation = true;

        continueAbility(selectDeviceId);
    }

    /**
     * 设置选择设备Id
     * @param deviceId
     */
    public static void setDeviceId(String deviceId) {
        selectDeviceId = deviceId;
    }
    @Override
    public void onActive() {
        super.onActive();
    }
    @Override
    public void onForeground(Intent intent) {
        super.onForeground(intent);
    }
    @Override
    public boolean onStartContinuation() {
        return true;
    }
    @Override
    public boolean onSaveData(IntentParams intentParams) {
        // 流转前保存index
        intentParams.setParam("removeIndex", paramIndex);
        return true;
    }
    @Override
    public boolean onRestoreData(IntentParams intentParams) {
        // 获取流转过来的index
        removeIndex = Integer.parseInt(intentParams.getParam("removeIndex").toString());
        return true;
    }
    @Override
    public void onCompleteContinuation(int i) {
    }
}

这里说一下详情页参数index,有两个地方传递了,一个是在单设备时,从列表点击跳转到详情页,传递了参数index,另一个是服务流转到另一个设备时,流转前通过onSaveData保存index,到另一个设备通过onRestoreData获取到流转过来的index.

第三点就是使用封装好的DeviceDialog类,代码不多,我都添加注释了,把这个类理解了,分布式工作就省了不少代码了。

public class DeviceDialog {
    private static final HiLogLabel LABEL_LOG = new HiLogLabel(3, 0xD001100, "设备对话框");
    // 上下文
    private final Context context;
    // 获取流转任务管理服务管理类
    private final IContinuationRegisterManager continuationRegisterManager;
    // 注册传输任务管理服务后返回的能力令牌
    private int abilityToken;
    // 用户在设备列表中选择设备后返回的设备ID
    private String selectDeviceId;

    /**
     * 初始化设备对话框,设置传输任务管理服务管理类,并注册传输任务管理服务管理类。
     * @param continuationRegisterManager
     * @param slice
     */
    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);
    }
    // 设置流转任务管理服务设备状态变更的回调
    private final IContinuationDeviceCallback callback = new IContinuationDeviceCallback() {
        @Override
        public void onDeviceConnectDone(String str, String str1) {
            // 在用户选择设备后设置设备ID
            selectDeviceId = str;
            continuationRegisterManager.updateConnectStatus(abilityToken, selectDeviceId,
                    DeviceConnectState.CONNECTED.getState(), null);
            // 返回设备ID
            returnDeviceId();
        }

        @Override
        public void onDeviceDisconnectDone(String str) {
        }
    };
    // 设置注册流转任务管理服务回调
    private final RequestCallback requestCallback = new RequestCallback() {
        @Override
        public void onResult(int result) {
            abilityToken = result;
        }
    };
    /**
     * 返回设备ID
     */
    private void returnDeviceId() {
        HiLog.info(LABEL_LOG, "deviceid::" + selectDeviceId);
        // 将选择设备Id, 告诉RightAbilitySlice
        RightAbilitySlice.setDeviceId(selectDeviceId);
    }

    /**
     * 打开设备选择框
     *
     * @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);
    }

    /**
     * 断开流转任务管理服务
     *
     * @since 2021-09-10
     */
    public void clearRegisterManager() {
        // 解注册流转任务管理服务
        continuationRegisterManager.unregister(abilityToken, null);
        // 断开流转任务管理服务连接
        continuationRegisterManager.disconnect();
    }
}

到这里就介绍完我说的四个步骤了,帖子有些长,要有点耐心看才行,如果不能集中看完,也可以直接同步源码,先运行起来,看看效果,然后再一步一步的去理解就,最后合在一起就成了。

Gitee源码: https://gitee.com/army16/parallel-horizon-demo

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
已于2021-11-9 18:58:11修改
9
收藏 6
回复
举报
回复
添加资源
添加资源将有机会获得更多曝光,你也可以直接关联已上传资源 去关联
    相关推荐