当前位置: 首页 > news >正文

OpenHarmony后台服务开发指南:ServiceAbility与ServiceExtensionAbility全解析

概述

ServiceAbility是OpenHarmony中用于实现后台服务的组件,它可以在后台长时间运行,没有用户界面。ServiceAbility主要用于执行需要长时间运行的操作,如音乐播放、文件下载、数据同步等任务。

ServiceAbility具有以下特点:

  • 无用户界面,在后台运行
  • 可被其他组件(如Ability)启动或绑定
  • 可以在设备重启后自动启动(需要配置)
  • 支持多进程通信

ServiceAbility生命周期

ServiceAbility的生命周期包含以下关键回调方法:

生命周期方法说明
onStart()ServiceAbility创建时调用,用于初始化操作
onCommand()启动ServiceAbility时调用,可多次调用
onConnect()绑定ServiceAbility时调用,返回IRemoteObject对象
onDisconnect()解绑ServiceAbility时调用
onStop()ServiceAbility销毁时调用,用于资源清理

ServiceAbility配置

在module.json5文件中配置ServiceAbility:

{"module": {"abilities": [{"name": "ServiceAbility","srcEntry": "./ets/serviceability/ServiceAbility.ts","description": "$string:serviceability_desc","icon": "$media:icon","type": "service","backgroundModes": ["dataTransfer","audioPlayback"]}]}
}

配置项说明:

  • type:设置为"service"表示这是一个ServiceAbility
  • backgroundModes:指定后台运行模式,如数据传输、音频播放等

ServiceExtensionAbility概述

ServiceExtensionAbility是Stage模型中替代ServiceAbility的后台服务组件,主要面向系统应用。与ServiceAbility相比,ServiceExtensionAbility提供了更严格的生命周期管理和更安全的运行环境。

ServiceExtensionAbility有两种运行形式:

  1. 启动型:通过startServiceExtensionAbility启动
  2. 连接型:通过connectServiceExtensionAbility连接

ServiceExtensionAbility生命周期

ServiceExtensionAbility的生命周期包含以下回调方法:

生命周期方法说明
onCreate()ServiceExtensionAbility创建时调用
onRequest()启动ServiceExtensionAbility时调用
onConnect()绑定ServiceExtensionAbility时调用
onDisconnect()解绑ServiceExtensionAbility时调用
onDestroy()ServiceExtensionAbility销毁时调用

ServiceExtensionAbility开发步骤

1. 创建ServiceExtensionAbility

import { ServiceExtensionAbility, Want } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';const TAG: string = '[ServiceExtensionAbility]';
const DOMAIN_NUMBER: number = 0xFF00;export default class ServiceExtAbility extends ServiceExtensionAbility {onCreate(want: Want, launchMode: number) {hilog.info(DOMAIN_NUMBER, TAG, 'onCreate, want: %{public}s, launchMode: %{public}d', JSON.stringify(want), launchMode);}onRequest(want: Want, startId: number) {hilog.info(DOMAIN_NUMBER, TAG, 'onRequest, want: %{public}s, startId: %{public}d', JSON.stringify(want), startId);}onConnect(want: Want) {hilog.info(DOMAIN_NUMBER, TAG, 'onConnect, want: %{public}s', JSON.stringify(want));return null;}onDisconnect(want: Want) {hilog.info(DOMAIN_NUMBER, TAG, 'onDisconnect, want: %{public}s', JSON.stringify(want));}onDestroy() {hilog.info(DOMAIN_NUMBER, TAG, 'onDestroy');}
}

2. 配置ServiceExtensionAbility

在module.json5文件中配置:

{"module": {"extensionAbilities": [{"name": "ServiceExtAbility","srcEntry": "./ets/serviceextensionability/ServiceExtAbility.ts","description": "$string:serviceextability_desc","icon": "$media:icon","type": "service","visible": true}]}
}

3. 启动ServiceExtensionAbility

import { common } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';const TAG: string = '[Page_ServiceExtensionAbility]';
const DOMAIN_NUMBER: number = 0xFF00;@Entry
@Component
struct Page_ServiceExtensionAbility {build() {Column() {Button('启动后台服务').onClick(() => {let context = this.getUIContext().getHostContext() as common.UIAbilityContext;let want: Want = {bundleName: 'com.example.myapplication',abilityName: 'ServiceExtAbility'};context.startServiceExtensionAbility(want).then(() => {hilog.info(DOMAIN_NUMBER, TAG, 'startServiceExtensionAbility success');}).catch((error: BusinessError) => {hilog.error(DOMAIN_NUMBER, TAG, 'startServiceExtensionAbility failed');});})}}
}

4. 停止ServiceExtensionAbility

// 在ServiceExtensionAbility内部
this.terminateSelf();// 在外部组件中
context.stopServiceExtensionAbility(want).then(() => {hilog.info(DOMAIN_NUMBER, TAG, 'stopServiceExtensionAbility success');
}).catch((error: BusinessError) => {hilog.error(DOMAIN_NUMBER, TAG, 'stopServiceExtensionAbility failed');
});

连接ServiceExtensionAbility

1. 建立连接

import { common } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { BusinessError } from '@kit.BasicServicesKit';const TAG: string = '[Page_ServiceExtensionAbility]';
const DOMAIN_NUMBER: number = 0xFF00;let connectionId: number;@Entry
@Component
struct Page_ServiceExtensionAbility {build() {Column() {Button('连接后台服务').onClick(() => {let context = this.getUIContext().getHostContext() as common.UIAbilityContext;let want: Want = {bundleName: 'com.example.myapplication',abilityName: 'ServiceExtAbility'};let options: common.ConnectOptions = {onConnect(elementName, remote) {hilog.info(DOMAIN_NUMBER, TAG, 'onConnect callback');// 保存remote对象用于通信},onDisconnect(elementName) {hilog.info(DOMAIN_NUMBER, TAG, 'onDisconnect callback');},onFailed(code) {hilog.error(DOMAIN_NUMBER, TAG, 'onFailed callback');}};connectionId = context.connectServiceExtensionAbility(want, options);})}}
}

2. 断开连接

Button('断开连接').onClick(() => {let context = this.getUIContext().getHostContext() as common.UIAbilityContext;context.disconnectServiceExtensionAbility(connectionId).then(() => {hilog.info(DOMAIN_NUMBER, TAG, 'disconnectServiceExtensionAbility success');}).catch((error: BusinessError) => {hilog.error(DOMAIN_NUMBER, TAG, 'disconnectServiceExtensionAbility failed');});})

客户端与服务端通信

使用IDL接口通信(推荐)

// 客户端
import { common } from '@kit.AbilityKit';
import { rpc } from '@kit.IPCKit';
import IdlServiceExtProxy from '../IdlServiceExt/idl_service_ext_proxy';let options: common.ConnectOptions = {onConnect(elementName, remote: rpc.IRemoteObject) {let serviceExtProxy: IdlServiceExtProxy = new IdlServiceExtProxy(remote);// 通过接口调用的方式进行通信serviceExtProxy.processData(1, (errorCode: number, retVal: number) => {hilog.info(DOMAIN_NUMBER, TAG, `processData, errorCode: ${errorCode}, retVal: ${retVal}`);});},onDisconnect(elementName) {hilog.info(DOMAIN_NUMBER, TAG, 'onDisconnect callback');},onFailed(code: number) {hilog.error(DOMAIN_NUMBER, TAG, 'onFailed callback');}
};

使用MessageSequence通信

import { rpc } from '@kit.IPCKit';let options: common.ConnectOptions = {onConnect(elementName, remote: rpc.IRemoteObject) {let option = new rpc.MessageOption();let data = new rpc.MessageSequence();let reply = new rpc.MessageSequence();data.writeInt(99);remote.sendMessageRequest(REQUEST_CODE, data, reply, option).then((ret: rpc.RequestResult) => {let errCode = reply.readInt();let msg: number = 0;if (errCode === 0) {msg = reply.readInt();}hilog.info(DOMAIN_NUMBER, TAG, `sendRequest msg:${msg}`);});},onDisconnect(elementName) {hilog.info(DOMAIN_NUMBER, TAG, 'onDisconnect callback');},onFailed(code) {hilog.error(DOMAIN_NUMBER, TAG, 'onFailed callback');}
};

服务端对客户端身份校验

通过callerUid识别客户端应用

import { bundleManager } from '@kit.AbilityKit';
import { rpc } from '@kit.IPCKit';export default class ServiceExtImpl extends IdlServiceExtStub {processData(data: number, callback: ProcessDataCallback) {let callerUid = rpc.IPCSkeleton.getCallingUid();bundleManager.getBundleNameByUid(callerUid).then((callerBundleName) => {hilog.info(DOMAIN_NUMBER, TAG, 'getBundleNameByUid: ' + callerBundleName);// 对客户端包名进行识别if (callerBundleName !== 'com.samples.stagemodelabilitydevelop') {hilog.info(DOMAIN_NUMBER, TAG, 'The caller bundle is not in trustlist, reject');return;}// 识别通过,执行正常业务逻辑callback(ERR_OK, data + 1);}).catch((err: BusinessError) => {hilog.info(DOMAIN_NUMBER, TAG, 'getBundleNameByUid failed: ' + err.message);});}
}

通过callerTokenId对客户端进行鉴权

import { abilityAccessCtrl, bundleManager } from '@kit.AbilityKit';
import { rpc } from '@kit.IPCKit';export default class ServiceExtImpl extends IdlServiceExtStub {processData(data: number, callback: ProcessDataCallback) {let callerTokenId = rpc.IPCSkeleton.getCallingTokenId();let accessManger = abilityAccessCtrl.createAtManager();// 所校验的具体权限由开发者自行选择let grantStatus = accessManger.verifyAccessTokenSync(callerTokenId, 'ohos.permission.GET_BUNDLE_INFO_PRIVILEGED');if (grantStatus === abilityAccessCtrl.GrantStatus.PERMISSION_DENIED) {hilog.info(DOMAIN_NUMBER, TAG, 'PERMISSION_DENIED');callback(ERR_DENY, data); // 鉴权失败,返回错误return;}hilog.info(DOMAIN_NUMBER, TAG, 'verify access token success.');callback(ERR_OK, data + 1); // 鉴权通过,执行正常业务逻辑}
}

ServiceAbility向ServiceExtensionAbility迁移

迁移策略

  1. 系统应用:建议迁移至ServiceExtensionAbility
  2. 三方应用:根据业务类型选择场景化ExtensionAbility或公共模块/后台任务方案

生命周期对比

ServiceAbilityServiceExtensionAbility说明
onStart()onCreate()创建时的初始化
onCommand()onRequest()启动服务时的回调
onConnect()onConnect()绑定服务时的回调
onDisconnect()onDisconnect()解绑服务时的回调
onStop()onDestroy()销毁服务时的回调

总结

ServiceAbility和ServiceExtensionAbility是OpenHarmony中用于实现后台服务的重要组件。ServiceExtensionAbility作为Stage模型中的后台服务组件,提供了更严格的生命周期管理和更安全的运行环境,是系统应用开发的首选方案。通过合理使用这些组件,开发者可以实现各种后台服务功能,满足应用的不同需求。

http://www.dtcms.com/a/528180.html

相关文章:

  • ARM Cortex-M 向量表详解
  • 网站优化免费软件游戏推广话术
  • wxPython下载和安装教程(附安装包)
  • IOT项目——电源入门系列-第三章
  • 情绪合集 | 以往高分文献分析,揭示情绪研究热点
  • Vue中data和props数据代理的区别
  • C++容器queue
  • 运转灵活小企业网站建设wordpress文章布局
  • 网站网页框架构架图怎么做大理网站开发
  • Cliproxy与Adspower指纹浏览器:跨境业务安全与效率的双重引擎
  • 在线观看免费网站网址开源之家
  • AI降重软件开发方案:基于Python的文本语义重构系统
  • 小杰-自然语言处理(seven)——transformer系列——自注意力(self-attention)
  • 带代码示例的 HTML 标签实操手册
  • fastapi 前端文件配置 python fastapi服务添加前端打包好的静态文件
  • 计算机网络自顶向下方法3——详解分组交换时延、丢包、吞吐量
  • 外贸 网站推广青岛胶南市城乡建设局网站
  • GitHub等平台形成的开源文化正在重塑推荐人
  • webrtc代码走读(六)-QOS-FEC冗余度配置
  • F036 vue+flask中医热性药知识图谱可视化系统vue+flask+echarts+mysql
  • 电脑效能跃升利器 金士顿KVR内存焕新机
  • Bootstrap UI 编辑器
  • MySQL联合查询详解
  • webrtc代码走读(五)-QOS-FEC原理
  • 车载诊断架构 ---DTC快照中DID大小顺序是怎么要求的?
  • Windows 10 下 VS Code 配置 C++ 开发环境(MinGW)
  • 天津低价网站建设怎样做淘宝联盟的网站
  • 福建网站建建设方案太原关键词优化报价
  • 深耕 Rust:核心技术解析、生态实践与高性能开发指南
  • 深入浅出 Tokio 源码:掌握 Rust 异步编程的底层逻辑