HarmonyOS 鸿蒙Next实现多设备协同
HarmonyOS 鸿蒙Next实现多设备协同 在前面的文章中,已经介绍了如何实现跨设备迁移。本节在上节的基础上,稍作改造,以实现多设备之间的协同。
选择模板
选择Empty Ablity(Java)
创建项目
创建名为ContinueRemoteFACollaboration的项目作为演示
项目创建完成之后,会自动生成基础的代码结构,接下来直接在该结构上进行微调即可。
MainAbility实现implements IAbilityContinuation接口
MainAbility实现implements IAbilityContinuation接口,代码如下:
package com.waylau.hmos.continueremotefacollaboration;
import com.waylau.hmos.continueremotefacollaboration.slice.MainAbilitySlice;
import ohos.aafwk.ability.Ability;
import ohos.aafwk.ability.IAbilityContinuation;
import ohos.aafwk.content.Intent;
import ohos.aafwk.content.IntentParams;
import ohos.bundle.IBundleManager;
import ohos.security.SystemPermission;
import java.util.ArrayList;
import java.util.List;
/**
* 设备迁移与回迁
*
* @author <a href="https://waylau.com">Way Lau</a>
*/
public class MainAbility extends Ability implements IAbilityContinuation {
@Override
public void onStart(Intent intent) {
super.onStart(intent);
super.setMainRoute(MainAbilitySlice.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) {
}
}
上述代码,重点是重写onStartContinuation
、onSaveData
、onRestoreData
等方法。
申明权限
在项目的对应的config.json
中声明跨端迁移访问的权限:ohos.permission.DISTRIBUTED_DATASYNC
以及获取分布式设备信息的相关的权限。在config.json
中的配置如下:
{
"module": {
"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"
}
]
...
}
...
}
同时修改MainAbility
,显示申明ohos.permission.DISTRIBUTED_DATASYNC
权限,最终,MainAbility
完整代码如下:
package com.waylau.hmos.continueremotefacollaboration;
import com.waylau.hmos.continueremotefacollaboration.slice.MainAbilitySlice;
import ohos.aafwk.ability.Ability;
import ohos.aafwk.ability.IAbilityContinuation;
import ohos.aafwk.content.Intent;
import ohos.aafwk.content.IntentParams;
import ohos.security.SystemPermission;
import java.util.ArrayList;
import java.util.List;
/**
* 设备迁移与回迁
*
* @author <a href="https://waylau.com">Way Lau</a>
*/
public class MainAbility extends Ability implements IAbilityContinuation {
@Override
public void onStart(Intent intent) {
super.onStart(intent);
super.setMainRoute(MainAbilitySlice.class.getName());
requestPermission();
}
//获取权限
private void requestPermission() {
String[] permission = {
SystemPermission.DISTRIBUTED_DATASYNC
};
List<String> applyPermissions = new ArrayList<>();
for (String element : permission) {
if (verifySelfPermission(element) != 0) {
if (canRequestPermission(element)) {
applyPermissions.add(element);
}
}
}
requestPermissionsFromUser(applyPermissions.toArray(new String[0]), 0);
}
@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) {
}
}
设计界面与布局
修改ability_main.xml
布局文件如下:
<?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">
<TextField
ohos:id="$+id:message_textfield"
ohos:height="match_content"
ohos:width="match_parent"
ohos:hint="输入信息"
ohos:top_margin="100vp"
ohos:left_margin="24vp"
ohos:padding="5vp"
ohos:background_element="$graphic:background_ability_main"
ohos:text_alignment="center"
ohos:right_margin="24vp"
ohos:text_size="28vp"/>
<Button
ohos:id="$+id:button_continue_remote_fa"
ohos:height="match_content"
ohos:width="match_content"
ohos:top_margin="8vp"
ohos:background_element="$graphic:background_ability_main"
ohos:layout_alignment="horizontal_center"
ohos:text="迁移"
ohos:text_size="40vp"/>
</DirectionalLayout>
同时,修改background_ability_main.xml
样式文件如下:
<?xml version="1.0" encoding="UTF-8" ?>
<shape xmlns:ohos="http://schemas.huawei.com/res/ohos"
ohos:shape="rectangle">
<corners
ohos:radius="10"/>
<solid
ohos:color="#FAEBD7"/>
</shape>
修改MainAbilitySlice
核心的逻辑都集中到了MainAbilitySlice
中。MainAbilitySlice
同样也要实现implements IAbilityContinuation接口,代码如下:
public class MainAbilitySlice extends AbilitySlice implements IAbilityContinuation {
private static final String TAG = MainAbilitySlice.class.getSimpleName();
private static final HiLogLabel LABEL_LOG =
new HiLogLabel(HiLog.LOG_APP, 0x00001, TAG);
@Override
public void onStart(Intent intent) {
super.onStart(intent);
super.setUIContent(ResourceTable.Layout_ability_main);
}
@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) {
// 重写
// 保存回迁后恢复状态必须的数据
intentParams.setParam(MESSAGE_KEY, messageTextField.getText());
return true;
}
@Override
public boolean onRestoreData(IntentParams intentParams) {
// 重写
// 传递此前保存的数据
if (intentParams.getParam(MESSAGE_KEY) instanceof String) {
message = (String) intentParams.getParam(MESSAGE_KEY);
isContinued = true;
}
return true;
}
@Override
public void onCompleteContinuation(int i) {
// 终止
terminate();
}
}
上述代码,重点是重写onStartContinuation
、onSaveData
、onRestoreData
、onCompleteContinuation
等方法。其中,onSaveData
用于保存回迁后恢复状态必须的数据; onRestoreData
传递此前保存的数据。onCompleteContinuation
方法用于终止Page。
接着为“迁移”“回迁”按钮设置点击事件,代码如下:
private String message;
private boolean isContinued;
private TextField messageTextField;
@Override
public void onStart(Intent intent) {
super.onStart(intent);
super.setUIContent(ResourceTable.Layout_ability_main);
// 监听跨端迁移FA的事件
Button buttonContinueRemoteFA = (
Button) findComponentById(ResourceTable.Id_button_continue_remote_fa);
buttonContinueRemoteFA.setClickedListener(listener -> continueRemoteFA());
// 设置输入框内容
messageTextField = (TextField) findComponentById(ResourceTable.Id_message_textfield);
if (isContinued && message != null) {
messageTextField.setText(message);
}
}
private void continueRemoteFA() {
HiLog.info(LABEL_LOG, "before startRemoteFA");
String deviceId = DeviceUtils.getDeviceId();
HiLog.info(LABEL_LOG, "get deviceId: %{public}s", deviceId);
if (deviceId != null) {
// 发起迁移流程
// continueAbility()是不可回迁的
// continueAbilityReversibly() 是可以回迁的
continueAbility(deviceId);
}
}
上述代码:
- 可以通过
continueAbility
或者continueAbilityReversibly
方法来执行迁移。需要注意的是continueAbility()
是不可回迁的,而continueAbilityReversibly()
是可以回迁的。本例子是使用了continueAbility
方法。 continueAbility
方法可以指定待迁移的设备的ID,该ID通过DeviceUtils
工具类获取。- Message用于表示设备迁移时的状态数据。
DeviceUtils
DeviceUtils
代码如下:
package com.waylau.hmos.continueremotefacollaboration;
import ohos.distributedschedule.interwork.DeviceInfo;
import ohos.distributedschedule.interwork.DeviceManager;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;
import java.util.ArrayList;
import java.util.List;
/**
* 获取当前组网下可迁移的设备id列表
*
* @author <a href="https://waylau.com">Way Lau</a>
*/
public class DeviceUtils {
private static final String TAG = DeviceUtils.class.getSimpleName();
private static final HiLogLabel LABEL_LOG =
new HiLogLabel(HiLog.LOG_APP, 0x00001, TAG);
private DeviceUtils() {}
// 获取当前组网下可迁移的设备id列表
public static List<String> getAvailableDeviceId() {
List<String> deviceIds = new ArrayList<>();
List<DeviceInfo> deviceInfoList = DeviceManager.getDeviceList(DeviceInfo.FLAG_GET_ALL_DEVICE);
if (deviceInfoList == null) {
return deviceIds;
}
if (deviceInfoList.size() == 0) {
HiLog.warn(LABEL_LOG, "did not find other device");
return deviceIds;
}
for (DeviceInfo deviceInfo : deviceInfoList) {
deviceIds.add(deviceInfo.getDeviceId());
}
return deviceIds;
}
// 获取当前组网下可迁移的设备id
// 如果有多个则取第一个
public static String getDeviceId() {
String deviceId = "";
List<String> outerDevices = DeviceUtils.getAvailableDeviceId();
if (outerDevices == null || outerDevices.size() == 0) {
HiLog.warn(LABEL_LOG, "did not find other device");
} else {
for (String item : outerDevices) {
HiLog.info(LABEL_LOG, "outerDevices:%{public}s", item);
}
deviceId = outerDevices.get(0);
}
HiLog.info(LABEL_LOG, "getDeviceId:%{public}s", deviceId);
return deviceId;
}
}
DeviceUtils
的getDeviceId
方法用于获取在线设备列表。如果有多个,则取任意一个。
运行
为了演示多个设备的迁移情况,需要启动“Super device”,同时启动手机和平台两个模拟器。
将项目同时在这两个模拟器里面运行。
此时,假设手机为设备A,作为源设备,平台为设备B,作为目标设备。
在设备A上,在输入框中输入一些信息,比如“hello”。
而后点击“迁移”按钮,此时可以看到,Page已经迁移到了设备B上了。说明迁移成功了。
在设备B上可以继续对输入框进行编辑,比如输入“world”。
而后点击“迁移”按钮,此时可以看到,Page从设备B迁移到了设备A了。同时,在设备B上输入的内容,也同时迁移到了设备A上,这样就实现了多设备之间的协同。
参考
更多关于HarmonyOS 鸿蒙Next实现多设备协同的实战教程也可以访问 https://www.itying.com/category-93-b0.html
为啥我的app流转到电视上不是全屏呢?
更多关于HarmonyOS 鸿蒙Next实现多设备协同的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
HarmonyOS Next通过分布式技术实现多设备协同,主要包括以下关键技术:
-
分布式软总线:通过虚拟化的通信方式,将不同设备的硬件能力整合成一个“超级终端”,实现设备间的无缝连接。
-
分布式数据管理:跨设备数据同步与共享,确保数据一致性,提升用户体验。
-
分布式任务调度:根据设备性能和用户需求,智能分配任务,优化资源利用。
-
统一控制中心:用户可通过一个设备集中管理所有连接的设备,简化操作流程。
这些技术共同构建了HarmonyOS Next的多设备协同能力,提升了跨设备操作的便捷性和效率。