目录: 1、跨设备启动FA、跨设备迁移、回迁 2、跨设备连接Service 3、更多文章 重点撸代码: 1、跨设备启动FA、跨设备迁移、回迁 (1)权限 ohos.permission.DISTRIBUTED_DEVICE_STATE_CHANG…
目录:
1、跨设备启动FA、跨设备迁移、回迁
2、跨设备连接Service
3、更多文章

重点撸代码:
1、跨设备启动FA、跨设备迁移、回迁
(1)权限
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| ohos.permission.DISTRIBUTED_DEVICE_STATE_CHANGE:用于允许监听分布式组网内的设备状态变化。 ohos.permission.GET_DISTRIBUTED_DEVICE_INFO:用于允许获取分布式组网内的设备列表和设备信息。 ohos.permission.GET_BUNDLE_INFO:用于查询其他应用的信息。 ohos.permission.DISTRIBUTED_DATASYNC:用于允许不同设备间的数据交换。
"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"} ]
requestPermissionsFromUser(new String[]{"ohos.permission.DISTRIBUTED_DATASYNC"}, 0);
|
(2)界面:ability_main.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| <?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:orientation="vertical">
<Button ohos:id="$+id:main_start_fa_btn" ohos:height="match_content" ohos:width="300vp" ohos:text="1.启动远程���备的FA" ohos:text_size="20fp" ohos:text_color="#ffffff" ohos:background_element="$graphic:button_bg" ohos:layout_alignment="horizontal_center" ohos:top_padding="8vp" ohos:bottom_padding="8vp" ohos:left_padding="40vp" ohos:right_padding="40vp" ohos:top_margin="20vp" />
<Button ohos:id="$+id:main_migration_btn" ohos:height="match_content" ohos:width="300vp" ohos:text="2.迁移到远程设备" ohos:text_size="20fp" ohos:text_color="#ffffff" ohos:background_element="$graphic:button_bg" ohos:layout_alignment="horizontal_center" ohos:top_padding="8vp" ohos:bottom_padding="8vp" ohos:left_padding="40vp" ohos:right_padding="40vp" ohos:top_margin="20vp" /> </DirectionalLayout>
|
button_bg.xml
1 2 3 4 5 6
| <?xml version="1.0" encoding="utf-8"?> <shape xmlns:ohos="http://schemas.huawei.com/res/ohos" ohos:shape="rectangle"> <solid ohos:color="#007DFF"/> <corners ohos:radius="40"/> </shape>
|
另外我们需要的Page Abiltiy:MigrationAbility、RemoveAbility MainAbilitySlice:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
| public class MainAbilitySlice extends AbilitySlice { private Button mainStartFABtn,mainMigrationBtn;
@Override public void onStart(Intent intent) { super.onStart(intent); super.setUIContent(ResourceTable.Layout_ability_main); mainStartFABtn = (Button)findComponentById(ResourceTable.Id_main_start_fa_btn); mainMigrationBtn = (Button)findComponentById(ResourceTable.Id_main_migration_btn); mainStartFABtn.setClickedListener(mClickListener); mainMigrationBtn.setClickedListener(mClickListener); }
private Component.ClickedListener mClickListener = new Component.ClickedListener() { @Override public void onClick(Component component) { int compoentId = component.getId(); switch (compoentId){ case ResourceTable.Id_main_start_fa_btn: Intent intent = new Intent(); Operation op = new Intent.OperationBuilder() .withDeviceId(Common.getOnLineDeviceId()) .withBundleName("com.ybzy.demo") .withAbilityName("com.ybzy.demo.RemoveAbility") .withFlags(Intent.FLAG_ABILITYSLICE_MULTI_DEVICE) .build(); intent.setOperation(op); intent.setParam("msg","我夸设备把你这个FA拉起来了!"); startAbility(intent);
intent.setElement(new ElementName(Common.getOnLineDeviceId() ,"com.ybzy.demo","com.ybzy.demo.RemoveAbility")); intent.setFlags(Intent.FLAG_ABILITYSLICE_MULTI_DEVICE); intent.setParam("msg","我夸设备把你这个FA拉起来了!"); startAbility(intent);
break; case ResourceTable.Id_main_migration_btn: Intent migrationIntent = new Intent(); migrationIntent.setElement(new ElementName("","com.ybzy.demo" ,"com.ybzy.demo.MigrationAbility")); startAbility(migrationIntent); break; default: break; } } };
@Override public void onActive() { super.onActive(); }
@Override public void onForeground(Intent intent) { super.onForeground(intent); } }
|
ability_migration.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
| <?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:background_element="#00ffff" ohos:orientation="vertical">
<Text ohos:id="$+id:migration_text" ohos:height="match_content" ohos:width="250vp" ohos:background_element="#0088bb" ohos:layout_alignment="horizontal_center" ohos:text="下面是一个可编辑的文本框" ohos:text_size="50" ohos:padding="5vp" ohos:top_margin="30vp" />
<TextField ohos:id="$+id:migration_textfield" ohos:height="250vp" ohos:width="250vp" ohos:hint="请输入..." ohos:layout_alignment="horizontal_center" ohos:background_element="#ffffff" ohos:text_color="#888888" ohos:text_size="20fp" ohos:padding="5vp" /> <Button ohos:id="$+id:migration_migration_btn" ohos:height="match_content" ohos:width="match_content" ohos:text="点击迁移" ohos:text_size="20fp" ohos:text_color="#ffffff" ohos:background_element="$graphic:button_bg" ohos:top_padding="8vp" ohos:bottom_padding="8vp" ohos:left_padding="50vp" ohos:right_padding="50vp" ohos:layout_alignment="horizontal_center" ohos:top_margin="30vp" />
<Button ohos:id="$+id:migration_migration_back_btn" ohos:height="match_content" ohos:width="match_content" ohos:text="点击迁移回来" ohos:text_size="20fp" ohos:text_color="#ffffff" ohos:background_element="$graphic:button_bg" ohos:top_padding="8vp" ohos:bottom_padding="8vp" ohos:left_padding="50vp" ohos:right_padding="50vp" ohos:layout_alignment="horizontal_center" ohos:top_margin="30vp" /> </DirectionalLayout>
|
RemoveAbility…把接收到的值显示到页面就行,setText()
(3)工具类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| public class Common{ public static String getDeviceId(){ List<DeviceInfo> deviceList = DeviceManager.getDeviceList(DeviceInfo.FLAG_GET_ONLINE_DEVICE); if(deviceList.isEmpty()){ return null; } int deviceNum = deviceList.size(); List<String> deviceIds = new ArrayList<>(deviceNum); List<String> deviceNames = new ArrayList<>(deviceNum); deviceList.forEach((device)->{ deviceIds.add(device.getDeviceId()); deviceNames.add(device.getDeviceName()); });
String devcieIdStr = deviceIds.get(0); return devcieIdStr; }
public static void myShowTip(Context context,String msg){ Text text = new Text(context); text.setWidth(MATCH_CONTENT); text.setHeight(MATCH_CONTENT); text.setTextSize(16, Text.TextSizeType.FP); text.setText(msg); text.setPadding(30,20,30,20); text.setMultipleLine(true); text.setMarginLeft(30); text.setMarginRight(30); text.setTextColor(Color.WHITE); text.setTextAlignment(TextAlignment.CENTER); ShapeElement style = new ShapeElement(); style.setShape(ShapeElement.RECTANGLE); style.setRgbColor(new RgbColor(77,77,77)); style.setCornerRadius(15); text.setBackground(style); DirectionalLayout mainLayout = new DirectionalLayout(context); mainLayout.setWidth(MATCH_PARENT); mainLayout.setHeight(MATCH_CONTENT); mainLayout.setAlignment(LayoutAlignment.CENTER); mainLayout.addComponent(text); ToastDialog toastDialog = new ToastDialog(context); toastDialog.setSize(MATCH_PARENT,MATCH_CONTENT); toastDialog.setDuration(1500); toastDialog.setAutoClosable(true); toastDialog.setTransparent(true); toastDialog.setAlignment(LayoutAlignment.CENTER); toastDialog.setComponent((Component) mainLayout); toastDialog.show(); } }
|
(4)实现功能 MigrationAbilitySlice:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
| public class MigrationAbilitySlice extends AbilitySlice implements IAbilityContinuation { TextField migrationTextField; Button migrationMigrationBtn,migrationMigrationBackBtn; String msg = "";
@Override public void onStart(Intent intent) { super.onStart(intent); super.setUIContent(ResourceTable.Layout_ability_migration);
migrationTextField = (TextField)findComponentById(ResourceTable.Id_migration_textfield); migrationTextField.setText(msg); migrationMigrationBtn = (Button)findComponentById(ResourceTable.Id_migration_migration_btn); migrationMigrationBtn.setClickedListener(component -> { String deviceId = Common.getOnLineDeviceId(); if(deviceId != null){
continueAbilityReversibly(deviceId); } });
migrationMigrationBackBtn = (Button) findComponentById(ResourceTable .Id_migration_migration_back_btn); migrationMigrationBackBtn.setClickedListener(component -> { reverseContinueAbility(); }); }
@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("msg",migrationTextField.getText()); return true; }
@Override public boolean onRestoreData(IntentParams intentParams) { msg = intentParams.getParam("msg").toString();
return true; }
@Override public void onCompleteContinuation(int i) {
}
}
|
2、跨设备连接Service
启动远程设备Service的代码示例如下: 添加按钮:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| <Button ohos:id="$+id:main_start_removeService_btn" ohos:height="match_content" ohos:width="300vp" ohos:text="远程启动ServiceAbility" ohos:text_size="20fp" ohos:text_color="#ffffff" ohos:background_element="$graphic:button_bg" ohos:layout_alignment="horizontal_center" ohos:top_padding="8vp" ohos:bottom_padding="8vp" ohos:left_padding="40vp" ohos:right_padding="40vp" ohos:top_margin="20vp" /> <Button ohos:id="$+id:main_stop_removeService_btn" ohos:height="match_content" ohos:width="300vp" ohos:text="远程关闭ServiceAbility" ohos:text_size="20fp" ohos:text_color="#ffffff" ohos:background_element="$graphic:button_bg" ohos:layout_alignment="horizontal_center" ohos:top_padding="8vp" ohos:bottom_padding="8vp" ohos:left_padding="40vp" ohos:right_padding="40vp" ohos:top_margin="20vp" />
|
新建RemoteServiceAbility:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
| public class RemoteServiceAbility extends Ability { private static final HiLogLabel LABEL_LOG = new HiLogLabel(3, 0xD001100, "Demo"); private Source sVideoSource; private Player sPlayer;
@Override public void onStart(Intent intent) { HiLog.error(LABEL_LOG, "RmoteServiceAbility::onStart"); super.onStart(intent); Common.myShowTip(this,"remote onstart"); sPlayer = new Player(RemoteServiceAbility.this); new PlayerThread().start(); } class PlayerThread extends Thread { @Override public void run() { try { File mp3FilePath = getExternalFilesDir(Environment.DIRECTORY_MUSIC); if (!mp3FilePath.exists()) { mp3FilePath.mkdirs(); } File mp3File = new File(mp3FilePath.getAbsolutePath() + "/" + "bj.mp3");
Resource res = getResourceManager() .getRawFileEntry("resources/rawfile/bj.mp3").openRawFile(); byte[] buf = new byte[4096]; int count = 0; FileOutputStream fos = new FileOutputStream(mp3File); while ((count = res.read(buf)) != -1) { fos.write(buf, 0, count); } FileDescriptor fileDescriptor = new FileInputStream(mp3File).getFD(); sVideoSource = new Source(fileDescriptor); sPlayer.setSource(sVideoSource); sPlayer.prepare(); sPlayer.setVolume(0.3f); sPlayer.enableSingleLooping(true); sPlayer.play(); } catch (IOException e) { e.printStackTrace(); } } }
@Override public void onStop() { super.onStop(); Common.myShowTip(RemoteServiceAbility.this,"remote onStop"); sPlayer.stop(); }
@Override public IRemoteObject onConnect(Intent intent) { return null; } @Override public void onDisconnect(Intent intent) { } }
|
启动:
1 2 3 4 5 6 7 8 9 10 11 12
| case ResourceTable.Id_main_start_remoteService_btn:
Common.myShowTip(MainAbilitySlice.this,deviceId); Intent startRemoteServiceIntent = new Intent(); startRemoteServiceIntent.setElement(new ElementName( deviceId, "com.ybzy.demo", "com.ybzy.demo.RemoteServiceAbility" )); startRemoteServiceIntent.setFlags(Intent.FLAG_ABILITYSLICE_MULTI_DEVICE); startAbility(startRemoteServiceIntent); break;
|
关闭远程设备Service:
1 2 3 4 5 6 7 8 9 10 11
| case ResourceTable.Id_main_stop_remoteService_btn: Common.myShowTip(MainAbilitySlice.this,deviceId); Intent stopRemoteServiceIntent = new Intent(); stopRemoteServiceIntent.setElement(new ElementName( deviceId, "com.ybzy.demo", "com.ybzy.demo.RemoteServiceAbility" )); stopRemoteServiceIntent.setFlags(Intent.FLAG_ABILITYSLICE_MULTI_DEVICE); stopAbility(stopRemoteServiceIntent); break;
|
仅通过启动和停止Service Ability两种方式对Service进行调度无法应对需长期交互的场景, 简单地说,信息就是只能去,回不来! 因此,分布式任务调度平台向开发者提供了跨设备Service连接及断开连接的能力。 链接上了,信息可去可回! 链接是使用connectAbility()方法,需要传入目标Service的Intent与接口IAbilityConnection的实例对象。 接口IAbilityConnection提供了两个方法供开发者实现: (1)onAbilityConnectDone()用来处理连接的回调。 (2)onAbilityDisconnectDone()用来处理断开连接的回调。 我们可以在onAbilityConnectDone()中获取管理链接的代理,进一步为了使用该代理跨设备调度Service, 开发者需要在本地及远端分别实现对外接口一致的代理,这个接口是IRemoteBroker。 添加按钮:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| <Button ohos:id="$+id:main_connect_remoteService_btn" ohos:height="match_content" ohos:width="300vp" ohos:text="远程链接ServiceAbility" ohos:text_size="20fp" ohos:text_color="#ffffff" ohos:background_element="$graphic:button_bg" ohos:layout_alignment="horizontal_center" ohos:top_padding="8vp" ohos:bottom_padding="8vp" ohos:left_padding="40vp" ohos:right_padding="40vp" ohos:top_margin="20vp" />
<Button ohos:id="$+id:main_use_remoteService_btn" ohos:height="match_content" ohos:width="300vp" ohos:text="使用远程ServiceAbility" ohos:text_size="20fp" ohos:text_color="#ffffff" ohos:background_element="$graphic:button_bg" ohos:layout_alignment="horizontal_center" ohos:top_padding="8vp" ohos:bottom_padding="8vp" ohos:left_padding="40vp" ohos:right_padding="40vp" ohos:top_margin="20vp" />
<Button ohos:id="$+id:main_disconnect_remoteService_btn" ohos:height="match_content" ohos:width="300vp" ohos:text="远程断开ServiceAbility" ohos:text_size="20fp" ohos:text_color="#ffffff" ohos:background_element="$graphic:button_bg" ohos:layout_alignment="horizontal_center" ohos:top_padding="8vp" ohos:bottom_padding="8vp" ohos:left_padding="40vp" ohos:right_padding="40vp" ohos:top_margin="20vp" />
|
发起连接的本地侧的代理示例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| public class MyRemoteProxy implements IRemoteBroker { private static final int ERR_OK = 0; private static final int COMMAND_PLUS = IRemoteObject.MIN_TRANSACTION_ID;
private final IRemoteObject remote; public MyRemoteProxy(IRemoteObject remote) { this.remote = remote; }
@Override public IRemoteObject asObject() { return remote; }
public int plus(int a,int b) throws RemoteException { MessageParcel data = MessageParcel.obtain(); MessageParcel reply = MessageParcel.obtain();
MessageOption option = new MessageOption(MessageOption.TF_SYNC); data.writeInt(a); data.writeInt(b);
try { remote.sendRequest(COMMAND_PLUS, data, reply, option); int ec = reply.readInt(); if (ec != ERR_OK) { throw new RemoteException(); } int result = reply.readInt(); return result; } catch (RemoteException e) { throw new RemoteException(); } finally { data.reclaim(); reply.reclaim(); } } }
|
等待连接的远端侧的代理示例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| public class MyRemote extends RemoteObject implements IRemoteBroker{ private static final int ERR_OK = 0; private static final int ERROR = -1; private static final int COMMAND_PLUS = IRemoteObject.MIN_TRANSACTION_ID; public MyRemote() { super("MyService_Remote"); } @Override public IRemoteObject asObject() { return this; } @Override public boolean onRemoteRequest(int code, MessageParcel data, MessageParcel reply, MessageOption option) { if (code != COMMAND_PLUS) { reply.writeInt(ERROR); return false; } int value1 = data.readInt(); int value2 = data.readInt(); int sum = value1 + value2; reply.writeInt(ERR_OK); reply.writeInt(sum); return true; } }
|
等待连接侧还需要作如下修改:
1 2 3 4 5 6 7
| private MyRemote remote = new MyRemote(); @Override public IRemoteObject onConnect(Intent intent) { return remote.asObject(); }
|
完成上述步骤后,可以通过点击事件实现连接、利用连接关系控制PA以及断开连接等行为,代码示例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| private MyRemoteProxy mProxy = null;
private IAbilityConnection conn = new IAbilityConnection() { @Override public void onAbilityConnectDone(ElementName elementName, IRemoteObject iRemoteObject, int resultCode) { mProxy = new MyRemoteProxy(iRemoteObject); UIUtils.showTip(MainAbilitySlice.this,"拿到remoteObject:" + mProxy); }
@Override public void onAbilityDisconnectDone(ElementName elementName, int resultCode) { } };
case ResourceTable.Id_main_connect_remoteService_btn: if (deviceId != null) { Intent connectServiceIntent = new Intent(); connectServiceIntent.setElement(new ElementName( deviceId, "com.ybzy.demo", "com.ybzy.demo.RemoteServiceAbility" )); connectServiceIntent.setFlags(Intent.FLAG_ABILITYSLICE_MULTI_DEVICE); connectAbility(connectServiceIntent, iAbilityConnection); } break;
case ResourceTable.Id_main_use_remoteService_btn: if (mProxy != null) { int ret = -1; try { ret = mProxy.plus(10, 20); } catch (RemoteException e) { e.printStackTrace(); } Common.myShowTip(MainAbilitySlice.this, "获取的结果:" + ret); } break;
case ResourceTable.Id_main_disconnect_remoteService_btn: disconnectAbility(iAbilityConnection); break;
|
作者:zhonghongfa
想了解更多内容,请访问51CTO和华为合作共建的鸿蒙社区:https://harmonyos.51cto.com
本文标题: 推荐系列- 鸿蒙软总线跨设备访问该怎么玩——小总结
本文作者: OSChina
发布时间: 2021年04月15日 09:46
最后更新: 2023年06月29日 07:10
原始链接: https://haoxiang.eu.org/550c4454/
版权声明: 本文著作权归作者所有,均采用CC BY-NC-SA 4.0许可协议,转载请注明出处!