目录
1 -> FA模型综述
1.1 -> 整体架构
1.2 -> 应用包结构
1.3 -> 生命周期
1.4 -> 进程线程模型
2 -> PageAbility开发
2.1 -> 概述
2.1.1 ->功能简介
2.1.2 -> PageAbility的生命周期
2.1.3 -> 启动模式
2.2 -> featureAbility接口说明
2.3 -> 启动本地PageAbility
2.4 -> 生命周期接口说明
3 -> ServiceAbility开发
3.1 -> 场景介绍
3.2 -> 接口说明
3.3 -> 开发步骤
3.3.1 -> 创建Service
3.3.2 -> 启动Service
3.3.3 -> 停止Service
3.3.4 -> 连接本地Service
1 -> FA模型综述
1.1 -> 整体架构
HarmonyOS用户程序的开发本质上就是开发Ability。HarmonyOS系统是通过对Ability调度,结合系统提供的一致性调度契约对Ability进行生命周期管理,从而实现对用户程序的调度。
Ability框架在API 8及更早版本使用FA模型。FA模型中Ability分为PageAbility、ServiceAbility、DataAbility、FormAbility几种类型。其中:
- PageAbility是具备ArkUI实现的Ability,是用户具体可见并可以交互的Ability实例。
- ServiceAbility也是Ability一种,但是没有UI,提供其他Ability调用自定义的服务,在后台运行。
- DataAbility也是没有UI的Ability,提供其他Ability进行数据的增删查服务,在后台运行。
- FormAbility是卡片Ability,是一种界面展示形式。
1.2 -> 应用包结构
1.3 -> 生命周期
在所有Ability中,PageAbility因为具有界面,也是应用的交互入口,因此生命周期更加复杂。
PageAbility生命周期回调如下图所示:
其他类型Ability的生命周期可参考PageAbility生命周期去除前后台切换以及onShow的部分进行理解。可以在 app.js/app.ets 中重写生命周期函数,在对应的生命周期函数内处理应用相应逻辑。目前app.js环境中仅支持onCreate和onDestroy回调,app.ets环境支持全量生命周期回调。
1.4 -> 进程线程模型
应用独享独立进程,Ability独享独立线程,应用进程在Ability第一次启动时创建,并为启动的Ability创建线程,应用启动后再启动应用内其他Ability,会为每一个Ability创建相应的线程。每个Ability绑定一个独立的JSRuntime实例,因此Ability之间是隔离的。
2 -> PageAbility开发
2.1 -> 概述
2.1.1 ->功能简介
PageAbility是具备ArkUI实现的Ability,是开发者具体可见并可以交互的Ability实例。开发者通过IDE创建Ability时,IDE会自动创建相关模板代码。PageAbility相关能力通过单独的featureAbility实现,生命周期相关回调则通过app.js/app.ets中各个回调函数实现。
2.1.2 -> PageAbility的生命周期
PageAbility生命周期介绍(Ability Life Cycle):
PageAbility生命周期是PageAbility被调度到INACTIVE、ACTIVE、BACKGROUND等各个状态的统称。
Ability生命周期状态说明:
-
UNINITIALIZED:未初始状态,为临时状态,PageAbility被创建后会由UNINITIALIZED状态进入INITIAL状态。
-
INITIAL:初始化状态,也表示停止状态,表示当前PageAbility未运行,PageAbility被启动后由INITIAL态进入ACTIVE状态。
-
INACTIVE:失去焦点状态,表示当前窗口已显示但是无焦点状态。
-
ACTIVE:前台激活状态,表示当前窗口已显示,并获取焦点。
-
BACKGROUND:后台状态,表示当前PageAbility退到后台,PageAbility在被销毁后由BACKGROUND状态进入INITIAL状态,或者重新被激活后由BACKGROUND状态进入ACTIVE状态。
PageAbility提供生命周期回调,开发者可以在app.js/app.ets中重写生命周期相关回调函数 。目前app.js环境中仅支持onCreate和onDestroy回调,app.ets环境支持全量生命周期回调。
2.1.3 -> 启动模式
ability支持单实例和多实例两种启动模式。
在config.json中通过launchType配置项,可以配置具体的启动模式。
启动模式 | 描述 | 说明 |
standard | 多实例 | 每次startAbility都会启动一个新的实例 |
singleton | 单实例 | 系统中只存在唯一一个实例,startAbility时,如果已存在,则复用系统中的唯一一个实例 |
缺省情况下是singleton模式。
2.2 -> featureAbility接口说明
接口名 | 描述 |
void startAbility(parameter: StartAbilityParameter) | 启动Ability |
Context getContext(): | 获取应用Context |
void terminateSelf() | 结束Ability |
bool hasWindowFocus() | 是否获取焦点 |
2.3 -> 启动本地PageAbility
导入模块
import featureAbility from '@ohos.ability.featureAbility'
示例
import featureAbility from '@ohos.ability.featureAbility'
featureAbility.startAbility({
want:
{
action: "",
entities: [""],
type: "",
options: {
// Grant the permission to perform read operations on the URI.
authReadUriPermission: true,
// Grant the permission to perform write operations on the URI.
authWriteUriPermission: true,
// support forwarding the Want result to the ability.
abilityForwardResult: true,
// Enable ability continuation.
abilityContinuation: true,
// Specify that a component does not belong to ohos.
notOhosComponent: true,
// Specify that an ability is started.
abilityFormEnabled: true,
// Grant the permission for possible persisting on the URI.
authPersistableUriPermission: true,
// Grant the permission for possible persisting on the prefix URI.
authPrefixUriPermission: true,
// Support distributed scheduling system startup on multiple devices.
abilitySliceMultiDevice: true,
// A service ability is started regardless of whether the host application has been started.
startForegroundAbility: true,
// Install the specified ability if it is not installed.
installOnDemand: true,
// Return the result to the ability slice.
abilitySliceForwardResult: true,
// Install the specified ability with background mode if it is not installed.
installWithBackgroundMode: true
},
deviceId: "",
bundleName: "com.example.startability",
abilityName: "com.example.startability.MainAbility",
uri: ""
},
});
want参数也可以使用parameters参数,使用key-value的方式输入。
示例
import featureAbility from '@ohos.ability.featureAbility'
featureAbility.startAbility({
want:
{
bundleName: "com.example.startability",
uri: "",
parameters: {
abilityName: "com.example.startability.MainAbility"
}
},
});
2.4 -> 生命周期接口说明
接口名 | 描述 |
onShow() | Ability由后台不可见状态切换到前台可见状态调用onShow方法,此时用户在屏幕可以看到该Ability。 |
onHide() | Ability由前台切换到后台不可见状态时调用onHide方法,此时用户在屏幕看不到该Ability。 |
onDestroy() | 应用退出,销毁Ability对象前调用onDestroy方法,开发者可以在该方法里做一些回收资源、清空缓存等应用退出前的准备工作。 |
onCreate() | Ability第一次启动创建Ability时调用onCreate方法,开发者可以在该方法里做一些应用初始化工作。 |
onInactive() | Ability失去焦点时调用onInactive方法,Ability在进入后台状态时会先失去焦点,再进入后台。 |
onActive() | Ability切换到前台,并且已经获取焦点时调用onActive方法。 |
示例
开需要重写app.js/app.ets中相关生命周期回调函数,IDE模板默认生成onCreate()和onDestroy()方法,其他方法需要自行实现。
export default {
onCreate() {
console.info('Application onCreate')
},
onDestroy() {
console.info('Application onDestroy')
},
onShow(){
console.info('Application onShow')
},
onHide(){
console.info('Application onHide')
},
onInactive(){
console.info('Application onInactive')
},
onActive(){
console.info('Application onActive')
},
}
3 -> ServiceAbility开发
3.1 -> 场景介绍
基于Service模板的Ability主要用于后台运行任务(如执行音乐播放、文件下载等),但不提供用户交互界面。Service可由其他应用或Ability启动,即使用户切换到其他应用,Service仍将在后台继续运行。
3.2 -> 接口说明
接口名 | 描述 |
onStart | 该方法在创建Service的时候调用,用于Service的初始化。在Service的整个生命周期只会调用一次,调用时传入的Want应为空。 |
onCommand | 在Service创建完成之后调用,该方法在客户端每次启动该Service时都会调用,开发者可以在该方法中做一些调用统计、初始化类的操作。 |
onConnect | 在Ability和Service连接时调用。 |
onDisconnect | 在Ability与绑定的Service断开连接时调用。 |
onStop | 在Service销毁时调用。Service应通过实现此方法来清理任何资源,如关闭线程、注册的侦听器等。 |
3.3 -> 开发步骤
3.3.1 -> 创建Service
1. Service也是一种Ability,Ability为Service提供了以下生命周期方法,开发者可以重写这些方法,来添加其他Ability请求与Service Ability交互时的处理方法。
创建Service的代码示例如下:
export default {
onStart() {
console.log('ServiceAbility onStart');
},
onCommand(want, startId) {
console.log('ServiceAbility onCommand');
},
onConnect(want) {
console.log('ServiceAbility OnConnect');
return new FirstServiceAbilityStub('test');
},
onDisconnect(want) {
console.log('ServiceAbility OnDisConnect');
},
onStop() {
console.log('ServiceAbility onStop');
},
}
2. 注册Service。
Service也需要在应用配置文件config.json中进行注册,注册类型type需要设置为service。
{
"module": {
"abilities": [
{
"name": ".ServiceAbility",
"type": "service",
"visible": true
...
}
]
...
}
...
}
3.3.2 -> 启动Service
Ability为开发者提供了startAbility()方法来启动另外一个Ability。因为Service也是Ability的一种,开发者同样可以通过将Want传递给该方法来启动Service。
开发者可以通过构造包含bundleName与abilityName的Want对象来设置目标Service信息。参数的含义如下:
- bundleName:表示包名称。
- abilityName:表示待启动的Ability名称。
import featureAbility from '@ohos.ability.featureAbility';
let promise = featureAbility.startAbility(
{
want:
{
bundleName: "com.jstest.service",
abilityName: "com.jstest.service.ServiceAbility",
},
}
);
执行上述代码后,Ability将通过startAbility() 方法来启动Service。
- 如果Service尚未运行,则系统会先调用onStart()来初始化Service,再回调Service的onCommand()方法来启动Service。
- 如果Service正在运行,则系统会直接回调Service的onCommand()方法来启动Service。
3.3.3 -> 停止Service
Service一旦创建就会一直保持在后台运行,除非必须回收内存资源,否则系统不会停止或销毁Service。开发者可以在Service中通过terminateSelf()停止本Service。
3.3.4 -> 连接本地Service
如果Service需要与Page Ability或其他应用的Service Ability进行交互,则须创建用于连接的Connection。Service支持其他Ability通过connectAbility()方法与其进行连接。
在使用connectAbility()处理回调时,需要传入目标Service的Want与IAbilityConnection的实例。IAbilityConnection提供了以下方法供开发者实现:onConnect()是用来处理连接Service成功的回调,onDisconnect()是用来处理Service异常死亡的回调,onFailed()是用来处理连接Service失败的回调。
import prompt from '@system.prompt'
var option = {
onConnect: function onConnectCallback(element, proxy) {
console.log(`onConnectLocalService onConnectDone`)
if (proxy === null) {
prompt.showToast({
message: "Connect service failed"
})
return
}
let data = rpc.MessageParcel.create()
let reply = rpc.MessageParcel.create()
let option = new rpc.MessageOption()
data.writeInterfaceToken("connect.test.token")
proxy.sendRequest(0, data, reply, option)
prompt.showToast({
message: "Connect service success"
})
},
onDisconnect: function onDisconnectCallback(element) {
console.log(`onConnectLocalService onDisconnectDone element:${element}`)
prompt.showToast({
message: "Disconnect service success"
})
},
onFailed: function onFailedCallback(code) {
console.log(`onConnectLocalService onFailed errCode:${code}`)
prompt.showToast({
message: "Connect local service onFailed"
})
}
}
连接本地Service的代码示例如下:
import featureAbility from '@ohos.ability.featureAbility';
let connId = featureAbility.connectAbility(
{
bundleName: "com.jstest.service",
abilityName: "com.jstest.service.ServiceAbility",
},
{
onConnect: onConnectCallback,
onDisconnect: onDisconnectCallback,
onFailed: onFailedCallback,
},
);
同时,Service侧也需要在onConnect()时返回IRemoteObject,从而定义与Service进行通信的接口。onConnect()需要返回一个IRemoteObject对象,HarmonyOS提供了IRemoteObject的默认实现,用户可以通过继承rpc.RemoteObject来创建自定义的实现类。
Service侧把自身的实例返回给调用侧的代码示例如下:
import rpc from "@ohos.rpc";
class FirstServiceAbilityStub extends rpc.RemoteObject {
constructor(des: any) {
if (typeof des === 'string') {
super(des)
} else {
return
}
}
onRemoteRequest(code: number, data: any, reply: any, option: any) {
console.log(printLog + ` onRemoteRequest called`)
if (code === 1) {
let string = data.readString()
console.log(printLog + ` string=${string}`)
let result = Array.from(string).sort().join('')
console.log(printLog + ` result=${result}`)
reply.writeString(result)
} else {
console.log(printLog + ` unknown request code`)
}
return true;
}
感谢各位大佬支持!!!
互三啦!!!