选择模板
选择空能力(Java)
创建项目
创建 ContinueRemoteFA 名为 Collaborations 的项目作为演示
项目创建完成后,会自动生成基础的代码结构,接直接在该结构上进行微调。
MainAbility实现实现IAbilityContinuation接口
MainAbility实现IAbilityContinuation接口,代码实现如下:
包com.waylau.hmos。继续远程协作
;
导入com.waylau.hmos。continueremotefacollaboration.slice.MainAbilitySlice;
导入ohos.aafwk.ability.Ability;
导入ohos.aafwk.ability.IAbilityContinuation;
导入ohos.aafwk.content.Intent;
导入ohos.aafwk.content.IntentParams;
导入ohos.bundle.IBundleManager;
导入ohos.security.SystemPermission;
导入java.util.ArrayList;
导入java.util.List;
/**
* 设备迁移与回迁
*
*
@author <a href="https://waylau.com">Way Lau</a>
*/
公共类MainAbility扩展能力实现IAbilityContinuation {
@覆盖
公共无效onStart(意图意图){
超级.onStart(intent);
超级.setMainRoute(MainAbilitySlice.class .getName ());
}
@覆盖
公共布尔onStartContinuation() {
// 高精度
返回真;
}
@覆盖
公共布尔onSaveData(IntentParams intentParams){
// 高精度
返回真;
}
@覆盖
公共布尔onRestoreData(IntentParams intentParams){
// 高精度
返回真;
}
@覆盖
公共无效onCompleteContinuation(int i){
}
}
上述代码,重点是启动onStartContinuation、onSaveData、onRestoreData等方法。
申明权限
在项目的配置json.中跨声明端迁移访问的:ohos.DISTRIBUTED_DATASYNC 以及获取以下配置权限信息的相关权限。
{
“模块”: {
“请求权限”:[
{
“名称”:“ohos.permission.DISTRIBUTED_DATASYNC”
},
{
“名称”:“ohos.permission.DISTRIBUTED_DEVICE_STATE_CHANGE”
},
{
“名称”:“ohos.permission.GET_DISTRIBUTED_DEVICE_INFO”
},
{
“名称”:“ohos.permission.GET_BUNDLE_INFO”
}
]
...
}
...
}
修改MainAbility,显示申明ohos.permission.DISTRIBUTED_DATASYNC权限,最终,MainAbility完整代码如下:
包com.waylau.hmos.continueremotefacollaboration;
导入com.waylau.hmos.continueremotefacollaboration.slice.MainAbilitySlice;
导入ohos.aafwk.ability.Ability;
导入ohos.aafwk.ability.IAbilityContinuation;
导入ohos.aafwk.content.Intent;
导入ohos.aafwk.content.IntentParams;
导入ohos.security.SystemPermission;
导入java.util.ArrayList;
导入java.util.List;
/**
* 设备迁移与回迁
*
* @author <a href="https://waylau.com">Way Lau</a>
*/
公共类MainAbility扩展能力实现IAbilityContinuation {
@覆盖
公共无效onStart(意图意图){
超级.onStart(intent);
超级.setMainRoute(MainAbilitySlice.class .getName ());
请求权限();
}
//获取权限
私人无效请求权限(){
字符串[] 权限 = {
系统权限。DISTRIBUTED_DATASYNC
};
List<String> applyPermissions = new ArrayList<>();
对于(字符串元素:权限){
if (verifySelfPermission(element) != 0) {
如果(canRequestPermission(元素)){
applyPermissions.add(element);
}
}
}
requestPermissionsFromUser(applyPermissions.toArray( new String[0]), 0);
}
@覆盖
公共布尔onStartContinuation() {
// 高精度
返回真;
}
@覆盖
公共布尔onSaveData(IntentParams intentParams){
// 高精度
返回真;
}
@覆盖
公共布尔onRestoreData(IntentParams intentParams){
// 高精度
返回真;
}
@覆盖
公共无效onCompleteContinuation(int i){
}
}
设计界面与布局
修改ability_main.xml布局文件如下:
<? xml 版本="1.0" 编码="utf-8" ?>
<定向布局
xmlns:ohos="http://schemas.huawei.com/res/ohos"
ohos:height="match_parent"
ohos:width="match_parent"
哦:对齐=“中心”
ohos:orientation="垂直" >
<文本字段
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" />
<按钮
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"
/>
</方向布局>
修改,background_ability_main.xml样式文件如下:
<? xml 版本="1.0" 编码="UTF-8" ?>
<形状 xmlns:ohos="http://schemas.huawei.com/res/ohos"
ohos:shape="矩形" >
<角落
ohos:radius="10" />
<固体
ohos:color="#FAEBD7" />
</形状>
最终,界面预览效果如下:
修改 MainAbilitySlice
核心的逻辑都集中到了MainAbilitySlice中。MainAbilitySlice同样要实现IAbilityContinuation接口,代码如下:
公共类MainAbilitySlice扩展AbilitySlice实现IAbilityContinuation {
私有静态最终字符串标签= MainAbilitySlice。类.getSimpleName();
私有静态最终HiLogLabel LABEL_LOG =
新HiLogLabel(HiLog.LOG_APP , 0x00001, TAG );
@覆盖
公共无效onStart(意图意图){
超级.onStart(intent);
超级.setUIContent(ResourceTable.Layout_ability_main ) ;
}
@覆盖
公共无效onActive() {
超级.onActive();
}
@覆盖
公共无效onForeground(意图意图){
超级.onForeground(意图);
}
@覆盖
公共布尔onStartContinuation() {
// 高精度
返回真;
}
@覆盖
公共布尔onSaveData(IntentParams intentParams){
// 高精度
// 保存回迁后恢复状态必须的数据
intentParams.setParam( MESSAGE_KEY , messageTextField .getText());
返回真;
}
@覆盖
公共布尔onRestoreData(IntentParams intentParams){
// 高精度
// 转移保存的数据
if (intentParams.getParam( MESSAGE_KEY ) instanceof String) {
message = (String) intentParams.getParam( MESSAGE_KEY );
isContinued = true ;
}
返回真;
}
@覆盖
公共无效onCompleteContinuation(int i){
// 结束
终止();
}
}
上面的代码,重点是运行onStartContinuation、onSaveData、onRestoreData、onCompleteContinuation等方法。其中,必须保存onSaveData回迁后恢复的数据;onRestoreData 准备好保存的数据。onCompleteContinuation。
为“迁移”“回迁”按钮设置点击事件,代码如下:
私人字符串消息;
private boolean isContinued ;
私人文本字段 messageTextField ;
@覆盖
公共无效onStart(意图意图){
超级.onStart(intent);
超级.setUIContent(ResourceTable.Layout_ability_main ) ;
// 监听跨端迁移FA的事件
按钮 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(消息);
}
}
私人无效continueRemoteFA() {
海洛格。信息(LABEL_LOG,“在 startRemoteFA 之前”);
字符串 deviceId = DeviceUtils。获取设备ID();
海洛格。info ( LABEL_LOG , "get deviceId: %{public}s" , deviceId);
if (deviceId != null ) {
// 启动迁移流程
// continueAbility()是不可回迁的
// continueAbilityReversibly() 是可以回迁的
continueAbility (deviceId);
}
}
上述代码:
可以通过continueAbility 或者continueAbilityReversibly 方法来执行迁移。需要注意的是的continueAbility() 是不可回迁的,而continueAbilityReversibly() 是可以回迁的。本例是使用了continueAbility 方法。
continueAbility 方法可以指定待迁移设备的 ID,该 ID 通过 DeviceUtils 工具类获取
消息表示设备迁移时的状态数据。
设备实用程序
DeviceUtils代码如下:
包com.waylau.hmos。继续远程协作;
导入ohos.distributedschedule.interwork.DeviceInfo;
导入ohos.distributedschedule.interwork.DeviceManager;
导入ohos.hiviewdfx.HiLog;
导入ohos.hiviewdfx.HiLogLabel;
导入java.util.ArrayList;
导入java.util.List;
/**
* 获取当前组网下可迁移的设备id列表
*
* @author <a href="https://waylau.com">Way Lau</a>
*/
公共类DeviceUtils {
私有静态最终字符串TAG = DeviceUtils。类.getSimpleName();
私有静态最终HiLogLabel LABEL_LOG =
新HiLogLabel(HiLog.LOG_APP , 0x00001, TAG );
私人DeviceUtils() {
}
// 获取当前组网下可迁移的设备id列表
公共静态列表<String> getAvailableDeviceId() {
List<String> deviceIds = new ArrayList<>();
列表<DeviceInfo> deviceInfoList =
装置经理。getDeviceList(设备信息。FLAG_GET_ALL_DEVICE);
if (deviceInfoList == null ) {
返回设备ID;
}
if (deviceInfoList.size() == 0) {
海洛格。warn ( LABEL_LOG , "没有找到其他设备" );
返回设备ID;
}
对于(设备信息设备信息:设备信息列表){
deviceIds.add(deviceInfo.getDeviceId());
}
返回设备ID;
}
// 获取当前组网下可迁移的设备id
// 如果有多个则取第一个
公共静态字符串 getDeviceId() {
字符串 deviceId = "" ;
列表<String> outerDevices = DeviceUtils。getAvailableDeviceId ();
if (outerDevices == null || outerDevices.size() == 0) {
海洛格。warn ( LABEL_LOG , "没有找到其他设备" );
}其他{
对于(字符串项目:outerDevices){
海洛格。info ( LABEL_LOG , "outerDevices:%{public}s" , item);
}
deviceId = outerDevices.get(0);
}
海洛格。info ( LABEL_LOG , "getDeviceId:%{public}s" , deviceId);
返回设备ID;
}
}
DeviceUtils 的 getDevice 方法获取在线设备。用于列表如果有多个,则取任意一个。
运行
再进行多人演示的迁移情况,需要启动“超级设备,同时启动手机和平台”两个设备。
将项目同时在这两个手机运行。
此时,假设手机为设备A,作为源设备,平台为设备B,作为目标设备。
在设备上,例如输入一些信息,“你好”
然后点击“迁移”按钮,此时可以看到已经迁移到了设备B上。说明迁移成功了。
在设备B上可以继续对输入框进行编辑,比如输入“世界”
然后点击“迁移”按钮,此时就可以看到,Page从设备B迁移到了设备A了。同时,在设备B上输入的内容,也同时迁移到了设备A上,这样就实现了多设备之间的协。