鸿蒙文档学习之Ability

856 阅读5分钟

一、Ability是什么

Ability是应用所具备能力的抽象,也是应用程序的重要组成部分。类似于Android的四大组件。

二、分类

Ability分为Feature Ability和Particle Ability两大类。

  • FA支持Page Ability,提供与用户的交互
  • PA支持Service Ability和Data Ability
    • SA提供后台服务的能力
    • DA提供对外部提供统一的数据访问的能力

(一)Page Ability

1.生命周期

Page生命周期.png

  • 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,在此期间的生命周期状态变化顺序为:

  1. FooAbilitySlice从ACTIVE状态变为INACTIVE状态。
  2. BarAbilitySlice则从INITIAL状态首先变为INACTIVE状态,然后变为ACTIVE状态(假定此前BarAbilitySlice未曾启动)。
  3. 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生命周期

ServiceAbility生命周期.jpg

  • 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定位资源:

URI.png

  • 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"
     ]
}
(2)创建DataAbilityHelper