

#2020征文-手机#【鸿蒙基地】鸿蒙跨设备启动窗口:Page Ability
source link: https://my.oschina.net/u/4857646/blog/4869383
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

目录:
HarmonyOS的核心特性(或称为卖点)之一就是软总线技术,而Page Ability的跨设备迁移是软总线的一个具体技术实现。所谓跨设备迁移Page Ability,是指设备A中的特定App调用设备B中该App的Page Ability。这有一个前提,就是设备A和设备B都安装了同一个App。如果B设备没有安装App,B设备就会自动从华为应用商店下载这个App,当然,这一过程是完全静默的。下载完后,就会自动启动相应的Page Ability。这种技术不仅可以启动另一个设备上的Page Ability,还可以向另一个设备中的Page Ability传递数据。
这种技术的一个主要应用场景是,可以将在设备A上完成了一半的工作,迁移到设备B上继续完成。例如,在家中平板电脑上要回一封EMail,但临时有急事,需要出门,这时可以将在平板电脑上写了一半的EMail迁移到手机上,需要在路上完成剩下的工作。
1. 跨设备迁移前的准备工作
在进行跨设备迁移之前,需要为HarmonyOS设备做一下准备:
(1) 打开HarmonyOS设备中的蓝牙;
(2)HarmonyOS设备需要连入Wi-Fi,而且多个HarmonyOS需要在同一个网段;
(3)多个HarmonyOS设备需要用同一个华为开发者账号登录,如图1所示。
图1 用同一个华为开发者账号登录
(4)点击“设置”>“更多连接”>“多设备协同”,进入多设备协同窗口,打开多设备协同开关,如图2所示。
图2 多设备协同
(5)修改HarmonyOS设备名。点击“设置”>“蓝牙”>“设备名称”,进入设备名称窗口,输入一个新的什么名称,如图3所示。尽管这一步不是必须的,但如果拥有多部HarmonyOS设备,可能很多HarmonyOS设备的名称是相同或相近的。为了更好区分不同的HarmonyOS设备,建议修改HarmonyOS设备名称。
图3 修改HarmonyOS设备名称
2 获取设备列表
跨设备迁移是通过设备ID来区分不同设备的,所以首先要获取所有可用的设备的ID。获取设备ID需要调用DeviceManager.getDeviceList方法,该方法返回一个List对象,类型是DeviceInfo,用来描述设备的相关信息,包括设备ID、设备名称(就是上一节设置的设备名称)等。实现代码如下:
List<DeviceInfo> deviceInfoList = DeviceManager.getDeviceList(DeviceInfo.FLAG_GET_ONLINE_DEVICE);
- getDeviceList方法有一个参数,是一个int类型的值,表示获取什么状态的设备的信息。可以指定的值如下:
(1) DeviceInfo.FLAG_GET_ONLINE_DEVICE:获取所有在线设备的信息;
(2) DeviceInfo. FLAG_GET_OFFLINE_DEVICE:获取所有离线设备的信息;
(3) DeviceInfo. FLAG_GET_ALL_DEVICE:获取所有设备的信息;
通常会使用第1个值,获取所有在线设备的信息,因为只有设备在线,才能将Page Ability迁移到该设备上。
下面给出一个案例,该案例实现了一个通用的显示可用设备列表的Page Ability,点击某一个设备,会返回该设备的ID,
在device_ids.xml布局文件中放置了一个ListContainer组件,用于显示获取的所有可用设备的相关信息。实现代码如下:
public class DeviceIdsAbility extends Ability {
// 保存获取到的所有设备的信息
private List<DeviceInfo> deviceInfos;
private ListContainer listContainerDeviceIds;
// 获取所有可用的设备的相关信息
public static List<DeviceInfo> getAvailableDeviceIds() {
List<DeviceInfo> deviceInfoList =
DeviceManager.getDeviceList(DeviceInfo.FLAG_GET_ONLINE_DEVICE);
if (deviceInfoList == null) {
return new ArrayList<>();
}
if (deviceInfoList.size() == 0) {
return new ArrayList<>();
}
return deviceInfoList;
}
@Override
public void onStart(Intent intent) {
super.onStart(intent);
super.setUIContent(ResourceTable.Layout_device_ids);
deviceInfos = getAvailableDeviceIds();
listContainerDeviceIds = 、
(ListContainer)findComponentById(ResourceTable.Id_listcontainer_deviceids);
if(listContainerDeviceIds != null) {
// 为ListContainer组件设置列表项监听器
listContainerDeviceIds.setItemClickedListener(new ListContainer.ItemClickedListener() {
@Override
public void onItemClicked(ListContainer listContainer, Component component, int i, long l) {
// 当单击某个列表项(设备)后,会获取该设备的ID,并将这个ID作为Page Ability
// 的结果返回
String deviceId = deviceInfos.get(i).getDeviceId();
Intent intent = new Intent();
intent.setParam("deviceId", deviceId);
setResult(100,intent);
// 关闭当前的Page Ability
terminateAbility();
}
});
// 为ListContainer组件设置Provider
listContainerDeviceIds.setItemProvider(new RecycleItemProvider() {
@Override
public int getCount() {
return deviceInfos.size();
}
@Override
public Object getItem(int i) {
return deviceInfos.get(i);
}
@Override
public long getItemId(int i) {
return i;
}
@Override
public Component getComponent(int i, Component component, ComponentContainer componentContainer) {
if(component == null) {
// 如果component为null,说明没有可以利用的列表项视图,所以要从布局文件
// 装载一个新的视图对象
component = (DirectionalLayout)LayoutScatter.getInstance(DeviceIdsAbility.this).parse(ResourceTable.Layout_device_id_item,null,false);
}
Text textDeviceName = (Text)component.findComponentById(ResourceTable.Id_text_device_name);
Text textDeviceId = (Text)component.findComponentById(ResourceTable.Id_text_device_id);
if(textDeviceName != null) {
// 显示设备名
textDeviceName.setText(deviceInfos.get(i).getDeviceName());
}
if(textDeviceId != null) {
// 显示设备ID
textDeviceId.setText(deviceInfos.get(i).getDeviceId());
}
return component;
}
});
}
}
}
在DeviceIdsAbility类中为ListContainer组件装载列表项时,在getComponent方法中利用了第2个参数component,该参数就是列表项的根视图。如果component为null,表明并没有可以利用的列表项视图,所以要创建一个新的列表项视图。如果不为null,表明可以利用其他的还没有显示的列表项视图,只需要替换该视图的Text组件中显示的信息即可。
最后在config.json文件中添加一些与分布式相关的权限。
"reqPermissions": [
{
"name": "ohos.permission.GET_DISTRIBUTED_DEVICE_INFO"
},
{
"name": "com.huawei.permission.ACCESS_DISTRIBUTED_ABILITY_GROUP"
},
{
"name": "ohos.permission.DISTRIBUTED_DATASYNC"
}
]
运行程序,会看到如图4所示的设备列表。
图4 获取可用设备的ID
要注意的是,通过DeviceManager.getDeviceList方法只能获取其他设备的信息,不能获取自身的信息,例如,有设备A、设备B和设备C。在设备A中只能获取设备B和设备C的信息,而不能获取设备A的信息。在设备B和设备C中的表现也类似。
作者:李宁
想了解更多内容,请访问: 51CTO和华为官方战略合作共建的鸿蒙技术社区https://harmonyos.51cto.com/
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK