HarmonyOS3.0发布之后,大家可以从api8上可以看到一个关键动作,就是完全抛弃了java,并且不提供对api8以下版本的兼容,完全颠覆性变化,显然不可能再去兼容低版本了。那么做过api7之前开发的朋友都会知道,在之前的js或者ets开发中,有几个关键地方是离不开java的,比如我前面一篇博客中写道的动态权限申请,本篇将来介绍另一个关键技术ServiceAbility,之前的ServiceAbility是完全基于Java开发,可以说和Android里面的开发模式一样。
下面就来上手尝试下ServiceAbility纯粹js或者ets开发吧,这里稍微吐槽下官方文档的不足吧,我已经反馈官方整改文档了。文档上的一些小错误和不足导致我打通Service的所有核心技能足足耗费了十多个小时,其中最难的莫过于Service主动给FA推送数据了,做过Android的可能都知道在Android里面这个是基于java的回调机制来实现,而这里官方文档是没有说这个核心技能是如何实现的,js的回调机制和java的回调机制还是有非常大区别的,我开始专在回调里面出不来导致耗费了很久时间,最后又尝试了N中方案终于最后找到了最优解搞定了这个核心功能。
本篇文章先主要来个Js版本的ServiceAbility开发入门吧。
场景介绍
基于Service模板的Ability(以下简称“Service”)主要用于后台运行任务(如执行音乐播放、文件下载等),但不提供用户交互界面。Service可由其他应用或Ability启动,即使用户切换到其他应用,Service仍将在后台继续运行。
接口说明
表1 Service中相关生命周期功能介绍
开发步骤
本篇先只实现最基本的创建、启动和停止Service。
创建工程
首先使用最新版的DevEco Studio(992版本)开发工具创建一个工程,选择最新的api8,如下图
创建工程时,需要关注的就是上图中所描述的bundleName和package,因为后面核心api中要使用到这两个参数,对于这两个参数含义不清楚的可以查阅我另外一篇博客《App与Hap、Entry与feature,bundleName与packge,务必弄明白》
创建Service
工程创建完成之后,鼠标选择js目录,然后点击鼠标右键,如下图依次选择来创建Service
Service也是一种Ability,Ability为Service提供了以下生命周期方法,开发者可以重写这些方法,来添加其他Ability请求与Service Ability交互时的处理方法。
创建Service的代码示例如下: export default {
onStart(want) {
console.info('ServiceAbility onStart');
},
onStop() {
console.info('ServiceAbility onStop');
},
onConnect(want) {
console.info('ServiceAbility onConnect');
return {};
},
onReconnect(want) {
console.info('ServiceAbility onReconnect');
},
onDisconnect() {
console.info('ServiceAbility onDisconnect');
},
onCommand(want, restart, startId) {
console.info('ServiceAbility onCommand');
}
};
本篇将只讲解启动和停止服务,等会写完启动和停止服务的触发代码之后,我们再来看看会有哪些生命周期函数会被回调。
由于Service也是Ability,创建完成Service之后,它也会自动的在应用配置文件config.json中生成相关核心配置信息,其中有个核心配置就是type为“service”,具体如下所示: {
"module": {
"abilities": [
{
"name": ".ServiceAbility",
"type": "service",
"visible": true
...
}
]
...
}
...
} 启动Service
做个极其简单的页面,只放置两个文本按钮,分别用来触发“启动Service”和“停止Service”,如下图
Ability为开发者提供了startAbility()方法来启动另外一个Ability。因为Service也是Ability的一种,开发者同样可以通过将Want传递给该方法来启动Service。
开发者可以通过构造包含bundleName与abilityName的Want对象来设置目标Service信息。参数的含义如下:
- bundleName:表示应用唯一标识符名称,即config.json中的bundleName。
- abilityName:表示待启动的Ability名称,这里使用完整Ability名称,即package+‘.’+Ability名称。
启动本地设备Service的代码示例如下:
首先要导入系统库
import featureAbility from ‘@ohos.ability.featureAbility’;
然后业务逻辑代码如下: //启动service按钮绑定的点击事件
onClickStartService(){
let promise = featureAbility.startAbility(
{
want:
{
bundleName: "com.xdw.jsdemo",
abilityName: "com.example.entry.ServiceAbility",
},
}
);
}
执行上述代码后,Ability将通过startAbility() 方法来启动Service。
- 如果Service尚未运行,则系统会先调用onStart()来初始化Service,再回调Service的onCommand()方法来启动Service。
- 如果Service正在运行,则系统会直接回调Service的onCommand()方法来启动Service。
不支持预览器进行测试,下面启动模拟器或者真机(必须api》=8)进行测试,多次点击“启动Service”按钮观察日志输出,日志输出如下图
停止Service
Service一旦创建就会一直保持在后台运行,除非必须回收内存资源,否则系统不会停止或销毁Service。开发者可以在Service中通过featureAbility.terminateSelf()停止本Service。
这里需要注意的是官方sdk目前并没有提供在其他Ability中主动停止Service的api,因此现在想简简单单的在UI中点击“停止service”按钮直接调用一个api停止service是做不到的,但并不是代表就不能通过点击按钮来停止服务,关于这个的实现下篇再讲。这里只讲通过在当前Service中通过featureAbility.terminateSelf()停止本Service。由于不是主动通过UI操作的,什么时候去停止服务需要个触发时机,最简单的就是在Service中添加一个定时器来做demo演示了。代码如下: onStart(want) {
console.info('ServiceAbility onStart');
//5秒之后停止Service
setTimeout(()=>{
console.info('delay 5秒');
featureAbility.terminateSelf();
},5000)
}, 但是这里尝试,发现尝试了好多次之后发现目前在Service中不支持setTimout定时器的运行,还不知道是有意这么设计的还是缺陷bug,已经反馈给华为官方进行跟进。那么只能换一种最low的方式来演示了,代码如下:onCommand(want, restart, startId) {
console.info('ServiceAbility onCommand');
featureAbility.terminateSelf();
} 最后运行日志截图如下:
小结
在官方文档基础上,把操作步骤和一些关键解释描述的更加详细,更加方便小白入手,防止入坑。
本篇只是入门级开胃小菜,我最终用这个Service的目的是为了在我智能家居的项目中,手机端通过该AbilityService实时接收服务端推送过来的数据,然后Service中接收到服务端推送过来的数据之后可以主动更新UI对应的Ability中的数据,即需要打通Service主动向Activity中传递数据这个关键技术点。详细打通流程会在下篇文章中讲解,这个是目前官网上面没有的内容。
|