一、Ability是什么
Ability是应用所具备能力的抽象,也是应用程序的重要组成部分。类似于Android的四大组件。
二、分类
Ability分为Feature Ability和Particle Ability两大类。
- FA支持Page Ability,提供与用户的交互
- PA支持Service Ability和Data Ability
- SA提供后台服务的能力
- DA提供对外部提供统一的数据访问的能力
(一)Page Ability
1.生命周期
- onStart()-onStop()分别在创建和销毁时调用;
- onForeground()-onBackground()分别和不可见时调用,其中onForeground()仅在onBackground()之后被调用;
- onActive()-onInActive()分别在得到焦点和失去焦点时被调用(即来到前台/可以交互)
销毁Page的可能原因包括以下几个方面:
- 用户通过系统管理能力关闭指定Page,例如使用任务管理器关闭Page。
- 用户行为触发Page的terminateAbility()方法调用,例如使用应用的退出功能。
- 配置变更导致系统暂时销毁Page并重建。
- 系统出于资源管理目的,自动触发对处于BACKGROUND状态Page的销毁。
2.注册
"abilities": [
{
"skills": [
{
"entities": [
"entity.system.home"
],
"actions": [
"action.system.home",
"action.next"
]
}
],
"orientation": "unspecified",
"name": "com.example.harmorytest.MainAbility",
"icon": "$media:icon",
"description": "$string:mainability_description",
"label": "$string:entry_MainAbility",
"type": "page",
"launchType": "standard"
},
{
"orientation": "unspecified",
"name": "com.example.harmorytest.SecondAbility",
"icon": "$media:icon",
"description": "$string:mainability_description",
"label": "$string:entry_MainAbility",
"type": "page",
"launchType": "standard"
}
]
3.AbilitySlice
(1)生命周期
AbilitySlice和Page具有相同的生命周期。 当Page的生命周期发生改变时,AbilitySlice的生命周期同时发生改变;但是AbilitySlice仍然具有独立于Page的生命周期:当AbilitySlice之间切换时Page的生命周期不变,但是AbilitySlice的生命周期会变化。
(2)Page与AbilitySlice生命周期关联
当AbilitySlice处于前台且具有焦点时,其生命周期状态随着所属Page的生命周期状态的变化而变化。当一个Page拥有多个AbilitySlice时,例如:MyAbility下有FooAbilitySlice和BarAbilitySlice,当前FooAbilitySlice处于前台并获得焦点,并即将导航到BarAbilitySlice,在此期间的生命周期状态变化顺序为:
- FooAbilitySlice从ACTIVE状态变为INACTIVE状态。
- BarAbilitySlice则从INITIAL状态首先变为INACTIVE状态,然后变为ACTIVE状态(假定此前BarAbilitySlice未曾启动)。
- FooAbilitySlice从INACTIVE状态变为BACKGROUND状态。
对应两个slice的生命周期方法回调顺序为: FooAbilitySlice.onInactive() --> BarAbilitySlice.onStart() --> BarAbilitySlice.onActive() --> FooAbilitySlice.onBackground()
(3)导航
同一Page内导航
直接调用present()方法:
//无需返回结果
present(new SecondScice(), new Intent());
//需要返回结果
@Override
protect void onStart() {
present(new SecondScice(), new Intent(), RESULT_CODE);
}
@Override
protect void setResult(int requestCode, Intent resultIntent) {
if (requestCode == RESULT_CODE) {
//从resultIntent中获取返回结果
}
}
不同Page内导航
AbilitySlice作为Page的内部组件,以Action的形式对外暴露,因此通过配置Intent的Action的方式导航到其他Page的AbilitySlice。
待更新
(4)AbilitySlice栈
系统为每个Page维护一个AbilitySlice栈,每个进入前台的AbilitySlice都会入栈。 当调用present()方法导航时,如果目标AS已经在栈中,则其上的AS均会被出栈
(二)Service Ability
1.Service生命周期
-
onStart() 该方法在创建Service的时候调用,用于Service的初始化。在Service的整个生命周期只会调用一次,调用时传入的Intent应为空。
-
onCommand() 在Service创建完成之后调用,该方法在客户端每次启动该Service时都会调用,用户可以在该方法中做一些调用统计、初始化类的操作。
-
onConnect() 在Ability和Service连接时调用,该方法返回IRemoteObject对象,用户可以在该回调函数中生成对应Service的IPC通信通道,以便Ability与Service交互。Ability可以多次连接同一个Service,系统会缓存该Service的IPC通信对象,只有第一个客户端连接Service时,系统才会调用Service的onConnect方法来生成IRemoteObject对象,而后系统会将同一个RemoteObject对象传递至其他连接同一个Service的所有客户端,而无需再次调用onConnect方法。
-
onDisconnect() 在Ability与绑定的Service断开连接时调用。
-
onStop() 在Service销毁时调用。Service应通过实现此方法来清理任何资源,如关闭线程、注册的侦听器等。
2.创建与注册
public class ServiceAbility extends Ability {
@Override
public void onStart(Intent intent) {
super.onStart(intent);
}
@Override
public void onCommand(Intent intent, boolean restart, int startId) {
super.onCommand(intent, restart, startId);
}
@Override
public IRemoteObject onConnect(Intent intent) {
return super.onConnect(intent); //自定义IRemoteObject类并创建对象返回给客户端
}
@Override
public void onDisconnect(Intent intent) {
super.onDisconnect(intent);
}
@Override
public void onStop() {
super.onStop();
}
}
"abilities": [
{
"name": ".ServiceAbility",
"type": "service",
"visible": true
...
}
]
3.启动与停止
启动ServiceAbility
Intent intent = new Intent();
Opeartion operation = new OperationBuilder()
.withDeviceId("deviceId") //远程设备id。如果启动本机的Service则传入空值
.withBundleName("bundleName") //包名。
.withAbilityName("abilityName") //Ability名
.withFlags(Intent.FLAG_ABILITYSLICE_MULTI_DEVICE) // 设置支持分布式调度系统多设备启动
.build();
intent.setOperation(operation);
startAbility(intent);
停止ServiceAbility
Service内部调用terminateAbility()或者外部Ability调用stopAbility(intent)
4.连接与断开
IAbilityConnection connection = new IAbilityConnection() {
@Override
public void onAbilityConnectionDone(ElementName name, IRemoteObject objcet,int resultCode){
//Client需要定义与Service相同的IRemoteObject实现类。
//开发者获取服务端传来的IRemoteObject对象,并从中解析出服务端传来的信息
}
@Override
public void onAbilityDisconnectDone(ElementName name, int resultCode) {
}
}
Intent intent = new Intent();
Operation operation = new OperationBuilder()
.withDeviceId("")
.withBundleName("")
.withAbilityName("")
.build();
intent.setOperation(operation);
connectAbility(intent, connection);
disconnectionAbility(connection);
5.前台Service
NotificationRequest request = new NotificationRequest(notificationId);
NotificationRequest.NotificationNormalContent content = new NotificationRequest.NotificationNormalContent();
NotificationRequest.NotificationContent nContent = new NotificationRequest.NotificationContent(content);
request.setContent(nContent);
keepBackgroundRunning(notificationId, request); //开启
cancelBackgroundRunning(); //停止
相应的配置config.json
{
"app": {}
"device": {}
"module": {
"reqPermissions": [
{
"name": "ohos.permission.KEEP_BACKGROUND_RUNNING",
"reason": "使用后台服务",
"usedScene": {
"ability": ["com.example.harmorytest.SecondAbility"],
"when": "always"
}
}
],
"abilities": [
{
"name": "com.example.harmorytest.SecondAbility",
"icon": "$media:icon",
"description": "$string:mainability_description",
"label": "$string:entry_MainAbility",
"type": "service",
"visible": true,
"backgroundModes": ["dataTransfer", "location"]
}
]
}
}
(三)DataAbility
用于共享数据。既支持与同设备不同应用共享,也支持跨设备共享。 DataAbility提供增删改查等接口,由开发者具体实现。
1.URI
DA通过URI定位资源:
- scheme:协议方案名,固定为“dataability”,代表Data Ability所使用的协议类型。
- authority:设备ID。如果为跨设备场景,则为目标设备的ID;如果为本地设备场景,则不需要填写。
- path:资源的路径信息,代表特定资源的位置信息。
- query:查询参数。
- fragment:可以用于指示要访问的子资源。 例如:
- 跨设备场景:dataability://device_id/com.domainname.dataability.persondata/person/10
- 本地设备:dataability:///com.domainname.dataability.persondata/person/10
2.创建和注册
右键src -> main -> java中的文件夹,选择File -> New -> Ability -> Empty Data Ability,之后重写对应的方法。 注册:
{
"name": ".UserDataAbility",
"type": "data",
"visible": true,
"uri": "dataability://com.example.myapplication5.DataAbilityTest",
"permissions": [
"com.example.myapplication5.DataAbility.DATA"
]
}
3.访问
(1)声明权限
{
"name": ".UserDataAbility",
"type": "data",
"visible": true,
"uri": "dataability://com.example.myapplication5.DataAbilityTest",
"permissions": [
"com.example.myapplication5.DataAbility.DATA"
]
}