目录
- 说些废话
- 开源代码
- 环境
- 代码
- ability_main.xml
- config.json
- MainAbility.java
- MainAbilitySlice.java
- 测试
说些废话
目前是2022-12-13,经有关核实,HarmonyOS2.0与3.0之间的回迁是无法有效果的。(3.0与3.0因为无机器测试所以暂不知。)然后也经过有关前辈报给华为那边了~
官方文档:跨端迁移开发指导(基于java开发) 下面环境里写的两台真机我测试的时候无法正常产生回迁效果,所以实际上我是用的远程模拟器操作成功的,但是我懒得删我的设备信息了。
模拟器不需要登录华为账号,但是需要在 设置-超级终端-允许被发现 处打开能够被附近设备发现。
开源代码
环境
HUAWEI MatePad Pro 10.8英寸 2019款 HarmonyOS3.0
Mate 10 Pro 全网通版 HarmonyOS2.0
DevEco Studio 3.0.0.993 Release
SDK 6(使用java)
我看的《公共事件开发指导》更新于2022-10-28 18:02
代码
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">
<Text
ohos:id="$+id:text_register"
ohos:height="match_content"
ohos:width="match_content"
ohos:layout_alignment="horizontal_center"
ohos:text="注册流转服务"
ohos:text_size="40vp"
/>
<Text
ohos:id="$+id:text_show"
ohos:height="match_content"
ohos:width="match_content"
ohos:layout_alignment="horizontal_center"
ohos:text="列出可流转的设备"
ohos:scrollable="true"
ohos:text_size="40vp"
/>
<Text
ohos:id="$+id:text_startMigration"
ohos:height="match_content"
ohos:width="match_content"
ohos:layout_alignment="horizontal_center"
ohos:text="开始迁移"
ohos:scrollable="true"
ohos:text_size="40vp"
/>
<Text
ohos:id="$+id:text_showParams"
ohos:height="match_content"
ohos:width="match_content"
ohos:layout_alignment="horizontal_center"
ohos:text="这里展示数据:无"
ohos:scrollable="true"
ohos:text_size="40vp"
/>
<Text
ohos:id="$+id:text_returnMigration"
ohos:height="match_content"
ohos:width="match_content"
ohos:layout_alignment="horizontal_center"
ohos:text="迁移回去"
ohos:scrollable="true"
ohos:text_size="40vp"
/>
</DirectionalLayout>
config.json
长度问题只放module部分。
"module": {
"package": "com.openvalley.cyj.migration",
"name": ".MyApplication",
"mainAbility": "com.openvalley.cyj.migration.MainAbility",
"deviceType": [
"phone",
"tablet"
],
"distro": {
"deliveryWithInstall": true,
"moduleName": "entry",
"moduleType": "entry",
"installationFree": false
},
"abilities": [
{
"skills": [
{
"entities": [
"entity.system.home"
],
"actions": [
"action.system.home"
]
}
],
"name": "com.openvalley.cyj.migration.MainAbility",
"description": "$string:mainability_description",
"icon": "$media:icon",
"label": "$string:entry_MainAbility",
"launchType": "standard",
"orientation": "unspecified",
"visible": true,
"type": "page"
}
],
"reqPermissions": [
{
"name": "ohos.permission.DISTRIBUTED_DATASYNC"
}
]
}
MainAbility.java
package com.openvalley.cyj.migration;
import com.openvalley.cyj.migration.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.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;
import ohos.security.SystemPermission;
public class MainAbility extends Ability implements IAbilityContinuation {
private static final HiLogLabel LABEL_LOG = new HiLogLabel(HiLog.LOG_APP, 0x00001, MainAbility.class.getSimpleName());
@Override
public void onStart(Intent intent) {
super.onStart(intent);
super.setMainRoute(MainAbilitySlice.class.getName());
verifyAndRequestSelfPermission();
}
/**
* 在此处验证和请求用户权限
*/
private void verifyAndRequestSelfPermission() {
try{
//返回值0有,-1没有
if(verifyCallingOrSelfPermission(SystemPermission.DISTRIBUTED_DATASYNC) == IBundleManager.PERMISSION_GRANTED){
// if(verifySelfPermission(SystemPermission.LOCATION) == IBundleManager.PERMISSION_GRANTED){
//如果有权限
}else {
//如果没授权就看这个权限能否动态授权
if(canRequestPermission(SystemPermission.DISTRIBUTED_DATASYNC)){
//如果可以弹窗授权
requestPermissionsFromUser(new String[] {SystemPermission.DISTRIBUTED_DATASYNC}, 0x10001);
}else {
//如果不能动态授权
return ;
}
}
}catch (Exception e){
e.printStackTrace();
}
}
/**
* 授权的回调
* @param requestCode
* @param permissions
* @param grantResults
*/
@Override
public void onRequestPermissionsFromUserResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsFromUserResult(requestCode, permissions, grantResults);
if(requestCode == 0x10001){
if(grantResults[0] == IBundleManager.PERMISSION_GRANTED){
//如果授权成功(0)
HiLog.info(LABEL_LOG, permissions[0] + "权限授权成功。");
}else {
//如果没有授权成功(-1)
return ;
}
}
}
/**
* 准备开始迁移的回调
* @return
*/
@Override
public boolean onStartContinuation() {
//返回值为true才发起迁移
HiLog.info(LABEL_LOG, "MainAbility onStartContinuation");
return true;
}
/**
* 当保存数据(要迁移的数据)的回调
* @param intentParams
* @return
*/
@Override
public boolean onSaveData(IntentParams intentParams) {
HiLog.info(LABEL_LOG, "MainAbility onSaveData");
return true;
}
/**
* 当恢复数据的回调(应该是被迁移的设备调用
* @param intentParams
* @return
*/
@Override
public boolean onRestoreData(IntentParams intentParams) {
//返回为true代表恢复数据成功
HiLog.info(LABEL_LOG, "MainAbility onRestoreData");
return true;
}
/**
* 迁移完成的回调
* @param i
*/
@Override
public void onCompleteContinuation(int i) {
HiLog.info(LABEL_LOG, " MainAbility onCompleteContinuation");
}
/**
* 迁移过程中失败的回调
*/
@Override
public void onRemoteTerminated() {
IAbilityContinuation.super.onRemoteTerminated();
HiLog.info(LABEL_LOG, "MainAbility onRemoteTerminated");
}
/**
* 回迁允许的情况下,远端中断
* @param errorCode
*/
@Override
public void onFailedContinuation(int errorCode) {
IAbilityContinuation.super.onFailedContinuation(errorCode);
HiLog.info(LABEL_LOG, "MainAbility onFailedContinuation");
}
}
MainAbilitySlice.java
package com.openvalley.cyj.migration.slice;
import com.openvalley.cyj.migration.ResourceTable;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.ability.IAbilityContinuation;
import ohos.aafwk.ability.continuation.*;
import ohos.aafwk.content.Intent;
import ohos.aafwk.content.IntentParams;
import ohos.agp.components.Text;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;
public class MainAbilitySlice extends AbilitySlice implements IAbilityContinuation {
private static final HiLogLabel LABEL_LOG = new HiLogLabel(HiLog.LOG_APP, 0x00001, MainAbilitySlice.class.getSimpleName());
Text text_register = null;
Text text_show = null;
Text text_startMigration = null;
Text text_showParams = null;
Text text_returnMigration = null;
IContinuationRegisterManager continuationRegisterManager = null;
IContinuationDeviceCallback continuationDeviceCallback = null;
RequestCallback requestCallback = null;
String jsonParams = null;
int abilityToken = 0;
String deviceId = null;
String params = null;
boolean isMigration = false;
@Override
public void onStart(Intent intent) {
super.onStart(intent);
super.setUIContent(ResourceTable.Layout_ability_main);
initContinuationRegisterManager();
initComponent();
}
/**
* 初始化注册管理类
*/
private void initContinuationRegisterManager(){
continuationRegisterManager = getContinuationRegisterManager();
//设备的回调(是在列出了设备列表后,选择某个设备进行流转连接成功或者断开时调用)
continuationDeviceCallback = new IContinuationDeviceCallback() {
@Override
public void onConnected(ContinuationDeviceInfo deviceInfo) {
HiLog.info(LABEL_LOG, "onConnected()");
deviceId = deviceInfo.getDeviceId();
HiLog.info(LABEL_LOG, "onConnected() 连接成功。 deviceId = " + deviceId);
continuationRegisterManager.updateConnectStatus(abilityToken, deviceId, DeviceConnectState.CONNECTED.getState(), requestCallback);
}
@Override
public void onDeviceConnectDone(String s, String s1) {
HiLog.info(LABEL_LOG, "onDeviceConnectDone()");
}
@Override
public void onDisconnected(String deviceId) {
HiLog.info(LABEL_LOG, "onDisconnected()");
}
@Override
public void onDeviceDisconnectDone(String s) {
HiLog.info(LABEL_LOG, "onDeviceDisconnectDone()");
}
};
//请求的回调(注册到服务中心成功)
requestCallback = new RequestCallback() {
@Override
public void onResult(int i) {
if(i > 0){
//为了保证更新数据时这个值还在,所以在if里写
abilityToken = i;
HiLog.info(LABEL_LOG, "onResult() 注册成功。 abilityToken = " + abilityToken);
}else {
HiLog.info(LABEL_LOG, "onResult() 其他操作。 abilityToken = " + i);
}
}
};
}
/**
* 初始化组件
*/
private void initComponent(){
text_register = (Text)findComponentById(ResourceTable.Id_text_register);
text_register.setClickedListener(listen -> register());
text_show = (Text)findComponentById(ResourceTable.Id_text_show);
text_show.setClickedListener(listen -> show());
text_startMigration = (Text)findComponentById(ResourceTable.Id_text_startMigration);
text_startMigration.setClickedListener(listen -> startMigration());
text_showParams = (Text)findComponentById(ResourceTable.Id_text_showParams);
text_showParams.setText("这里展示数据:" + params);
text_returnMigration = (Text)findComponentById(ResourceTable.Id_text_returnMigration);
text_returnMigration.setClickedListener(listen -> returnMigration());
}
/**
* 点击按钮进行流转服务注册
*/
private void register(){
if(continuationRegisterManager != null){
HiLog.info(LABEL_LOG, "register() 开始注册。");
continuationRegisterManager.register(getBundleName(), getExtraParams(), continuationDeviceCallback, requestCallback);
}
}
/**
* 展示可流转的设备
*/
private void show(){
if(continuationRegisterManager != null && abilityToken > 0){
continuationRegisterManager.showDeviceList(abilityToken, getExtraParams(), requestCallback);
}
}
/**
* 开始迁移
*/
private void startMigration(){
if(continuationRegisterManager != null && deviceId != null){
HiLog.info(LABEL_LOG, "startMigration() 开始迁移。");
// continueAbility(deviceId);
continueAbilityReversibly(deviceId);
isMigration = true;
HiLog.info(LABEL_LOG, "startMigration() 迁移结束。");
//如果是不回迁的,这边的页面就可以销毁掉
// terminateAbility();
}
}
/**
* 迁移回原设备
*/
private void returnMigration(){
// ContinuationState.
try{
boolean reverseContinueAbility = reverseContinueAbility();
HiLog.info(LABEL_LOG, "reverseContinueAbility = " + reverseContinueAbility);
isMigration = false;
}catch (Exception e){
HiLog.info(LABEL_LOG, "e = " + e.getMessage());
}
}
/**
* 获得注册时 额外的一些参数
* @return
*/
private ExtraParams getExtraParams(){
ExtraParams extraParams = new ExtraParams();
String[] devType = {ExtraParams.DEVICETYPE_SMART_PHONE, ExtraParams.DEVICETYPE_SMART_PAD};
//显示的列表包含那些设备类型
extraParams.setDevType(devType);
//添加描述(没出来)
extraParams.setDescription("这是一个描述。");
//如果不写,就会默认以注册时的BundleName作为targetBundleName
extraParams.setTargetBundleName(getBundleName());
//设备过滤
jsonParams = "\"{" +
"\"filter\":{" +
"\"commonFilter\":{" +
"\"system\":{" +
//目标设备对应的HarmonyOS版本 要≥
"\"harmonyVersion\":\"2.0.0\"" +
"}," +
// "}" +
//1为同账号,1|256为不同账号
"\"groupType\":\"1|256\"," +
//0x00000004需要在同一局域网下,0x00030004不需要在同一局域网下
"\"curComType\": 0x00030004," +
//为空就不做版本兼容性检查,要做版本兼容性检查时,需要传入目标应用包名。
"\"faFilter\":\"{" +
"\"targetBundleName\":\"com.openvalley.cyj.migration\"" +
"}\"" +
"}" +
"}," +
"\"transferScene\":0," +
"\"remoteAuthenticationDescription\": \"拉起HiVision扫描弹框描述\"" +
"}\"";
// HiLog.info(LABEL_LOG, jsonParams);
extraParams.setJsonParams(jsonParams);
return extraParams;
}
@Override
public void onActive() {
super.onActive();
}
@Override
public void onForeground(Intent intent) {
super.onForeground(intent);
}
@Override
protected void onStop() {
if(continuationRegisterManager != null && abilityToken > 0){
continuationRegisterManager.unregister(abilityToken, requestCallback);
}
}
/**
* 准备开始迁移的回调
* @return
*/
@Override
public boolean onStartContinuation() {
//返回值为true才发起迁移
HiLog.info(LABEL_LOG, "MainAbilitySlice onStartContinuation");
return true;
}
/**
* 当保存数据(要迁移的数据)的回调
* @param intentParams
* @return
*/
@Override
public boolean onSaveData(IntentParams intentParams) {
HiLog.info(LABEL_LOG, "MainAbilitySlice onSaveData");
intentParams.setParam("userName", "陈依劼");
return true;
}
/**
* 当恢复数据的回调(应该是被迁移的设备调用
* @param intentParams
* @return
*/
@Override
public boolean onRestoreData(IntentParams intentParams) {
//返回为true代表恢复数据成功
HiLog.info(LABEL_LOG, "MainAbilitySlice onRestoreData");
Object userName = intentParams.getParam("userName");
if(userName != null){
params = (String)userName;
}
return true;
}
/**
* 迁移完成的回调
* @param i
*/
@Override
public void onCompleteContinuation(int i) {
HiLog.info(LABEL_LOG, "MainAbilitySlice onCompleteContinuation");
}
/**
* 迁移过程中失败的回调
*/
@Override
public void onRemoteTerminated() {
HiLog.info(LABEL_LOG, "MainAbilitySlice onRemoteTerminated");
}
/**
* 回迁允许的情况下,远端中断
* @param errorCode
*/
@Override
public void onFailedContinuation(int errorCode) {
IAbilityContinuation.super.onFailedContinuation(errorCode);
HiLog.info(LABEL_LOG, "MainAbilitySlice onFailedContinuation");
}
}
测试
注意要先把想迁移到的设备的上的程序先授权。