HarmonyOS3.0嘗鮮之關(guān)鍵Js Api--ServiceAbility開(kāi)發(fā)
??想了解更多關(guān)于開(kāi)源的內(nèi)容,請(qǐng)?jiān)L問(wèn):??
??51CTO 開(kāi)源基礎(chǔ)軟件社區(qū)??
HarmonyOS3.0發(fā)布之后,大家可以從api8上可以看到一個(gè)關(guān)鍵動(dòng)作,就是完全拋棄了java,并且不提供對(duì)api8以下版本的兼容,完全顛覆性變化,顯然不可能再去兼容低版本了。那么做過(guò)api7之前開(kāi)發(fā)的朋友都會(huì)知道,在之前的js或者ets開(kāi)發(fā)中,有幾個(gè)關(guān)鍵地方是離不開(kāi)java的,比如我前面一篇博客中寫(xiě)道的動(dòng)態(tài)權(quán)限申請(qǐng),本篇將來(lái)介紹另一個(gè)關(guān)鍵技術(shù)ServiceAbility,之前的ServiceAbility是完全基于Java開(kāi)發(fā),可以說(shuō)和Android里面的開(kāi)發(fā)模式一樣。
下面就來(lái)上手嘗試下ServiceAbility純粹js或者ets開(kāi)發(fā)吧,這里稍微吐槽下官方文檔的不足吧,我已經(jīng)反饋官方整改文檔了。文檔上的一些小錯(cuò)誤和不足導(dǎo)致我打通Service的所有核心技能足足耗費(fèi)了十多個(gè)小時(shí),其中最難的莫過(guò)于Service主動(dòng)給FA推送數(shù)據(jù)了,做過(guò)Android的可能都知道在Android里面這個(gè)是基于java的回調(diào)機(jī)制來(lái)實(shí)現(xiàn),而這里官方文檔是沒(méi)有說(shuō)這個(gè)核心技能是如何實(shí)現(xiàn)的,js的回調(diào)機(jī)制和java的回調(diào)機(jī)制還是有非常大區(qū)別的,我開(kāi)始專在回調(diào)里面出不來(lái)導(dǎo)致耗費(fèi)了很久時(shí)間,最后又嘗試了N中方案終于最后找到了最優(yōu)解搞定了這個(gè)核心功能。
本篇文章先主要來(lái)個(gè)Js版本的ServiceAbility開(kāi)發(fā)入門(mén)吧。
場(chǎng)景介紹
基于Service模板的Ability(以下簡(jiǎn)稱“Service”)主要用于后臺(tái)運(yùn)行任務(wù)(如執(zhí)行音樂(lè)播放、文件下載等),但不提供用戶交互界面。Service可由其他應(yīng)用或Ability啟動(dòng),即使用戶切換到其他應(yīng)用,Service仍將在后臺(tái)繼續(xù)運(yùn)行。
接口說(shuō)明
表1 Service中相關(guān)生命周期功能介紹。
開(kāi)發(fā)步驟
本篇先只實(shí)現(xiàn)最基本的創(chuàng)建、啟動(dòng)和停止Service。
創(chuàng)建工程
首先使用最新版的DevEco Studio(992版本)開(kāi)發(fā)工具創(chuàng)建一個(gè)工程,選擇最新的api8,如下圖:
創(chuàng)建工程時(shí),需要關(guān)注的就是上圖中所描述的bundleName和package,因?yàn)楹竺婧诵腶pi中要使用到這兩個(gè)參數(shù),對(duì)于這兩個(gè)參數(shù)含義不清楚的可以查閱我另外一篇博客《??App與Hap、Entry與feature,bundleName與packge,務(wù)必弄明白??》。
創(chuàng)建Service
工程創(chuàng)建完成之后,鼠標(biāo)選擇js目錄,然后點(diǎn)擊鼠標(biāo)右鍵,如下圖依次選擇來(lái)創(chuàng)建Service。
Service也是一種Ability,Ability為Service提供了以下生命周期方法,開(kāi)發(fā)者可以重寫(xiě)這些方法,來(lái)添加其他Ability請(qǐng)求與Service Ability交互時(shí)的處理方法。
創(chuàng)建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');
}
};
本篇將只講解啟動(dòng)和停止服務(wù),等會(huì)寫(xiě)完啟動(dòng)和停止服務(wù)的觸發(fā)代碼之后,我們?cè)賮?lái)看看會(huì)有哪些生命周期函數(shù)會(huì)被回調(diào)。
由于Service也是Ability,創(chuàng)建完成Service之后,它也會(huì)自動(dòng)的在應(yīng)用配置文件config.json中生成相關(guān)核心配置信息,其中有個(gè)核心配置就是type為“service”,具體如下所示:
{
"module": {
"abilities": [
{
"name": ".ServiceAbility",
"type": "service",
"visible": true
}
]
}
}
啟動(dòng)Service
做個(gè)極其簡(jiǎn)單的頁(yè)面,只放置兩個(gè)文本按鈕,分別用來(lái)觸發(fā)“啟動(dòng)Service”和“停止Service”,如下圖:
Ability為開(kāi)發(fā)者提供了startAbility()方法來(lái)啟動(dòng)另外一個(gè)Ability。因?yàn)镾ervice也是Ability的一種,開(kāi)發(fā)者同樣可以通過(guò)將Want傳遞給該方法來(lái)啟動(dòng)Service。
開(kāi)發(fā)者可以通過(guò)構(gòu)造包含bundleName與abilityName的Want對(duì)象來(lái)設(shè)置目標(biāo)Service信息。參數(shù)的含義如下:
- bundleName:表示應(yīng)用唯一標(biāo)識(shí)符名稱,即config.json中的bundleName。
- abilityName:表示待啟動(dòng)的Ability名稱,這里使用完整Ability名稱,即package+‘.’+Ability名稱。?
啟動(dòng)本地設(shè)備Service的代碼示例如下:
首先要導(dǎo)入系統(tǒng)庫(kù)。
import featureAbility from ‘@ohos.ability.featureAbility’;
然后業(yè)務(wù)邏輯代碼如下:
//啟動(dòng)service按鈕綁定的點(diǎn)擊事件
onClickStartService(){
let promise = featureAbility.startAbility(
{
want:
{
bundleName: "com.xdw.jsdemo",
abilityName: "com.example.entry.ServiceAbility",
},
}
);
}
執(zhí)行上述代碼后,Ability將通過(guò)startAbility() 方法來(lái)啟動(dòng)Service。
- ? 如果Service尚未運(yùn)行,則系統(tǒng)會(huì)先調(diào)用onStart()來(lái)初始化Service,再回調(diào)Service的onCommand()方法來(lái)啟動(dòng)Service。
- 如?果Service正在運(yùn)行,則系統(tǒng)會(huì)直接回調(diào)Service的onCommand()方法來(lái)啟動(dòng)Service。?
不支持預(yù)覽器進(jìn)行測(cè)試,下面啟動(dòng)模擬器或者真機(jī)(必須api》=8)進(jìn)行測(cè)試,多次點(diǎn)擊“啟動(dòng)Service”按鈕觀察日志輸出,日志輸出如下圖:
停止Service
Service一旦創(chuàng)建就會(huì)一直保持在后臺(tái)運(yùn)行,除非必須回收內(nèi)存資源,否則系統(tǒng)不會(huì)停止或銷毀Service。開(kāi)發(fā)者可以在Service中通過(guò)featureAbility.terminateSelf()停止本Service。
這里需要注意的是官方sdk目前并沒(méi)有提供在其他Ability中主動(dòng)停止Service的api,因此現(xiàn)在想簡(jiǎn)簡(jiǎn)單單的在UI中點(diǎn)擊“停止service”按鈕直接調(diào)用一個(gè)api停止service是做不到的,但并不是代表就不能通過(guò)點(diǎn)擊按鈕來(lái)停止服務(wù),關(guān)于這個(gè)的實(shí)現(xiàn)下篇再講。這里只講通過(guò)在當(dāng)前Service中通過(guò)featureAbility.terminateSelf()停止本Service。由于不是主動(dòng)通過(guò)UI操作的,什么時(shí)候去停止服務(wù)需要個(gè)觸發(fā)時(shí)機(jī),最簡(jiǎn)單的就是在Service中添加一個(gè)定時(shí)器來(lái)做demo演示了。代碼如下:
onStart(want) {
console.info('ServiceAbility onStart');
//5秒之后停止Service
setTimeout(()=>{
console.info('delay 5秒');
featureAbility.terminateSelf();
},5000)
},
但是這里嘗試,發(fā)現(xiàn)嘗試了好多次之后發(fā)現(xiàn)目前在Service中不支持setTimout定時(shí)器的運(yùn)行,還不知道是有意這么設(shè)計(jì)的還是缺陷bug,已經(jīng)反饋給華為官方進(jìn)行跟進(jìn)。那么只能換一種最low的方式來(lái)演示了,代碼如下:
onCommand(want, restart, startId) {
console.info('ServiceAbility onCommand');
featureAbility.terminateSelf();
}
最后運(yùn)行日志截圖如下:
小結(jié)
在官方文檔基礎(chǔ)上,把操作步驟和一些關(guān)鍵解釋描述的更加詳細(xì),更加方便小白入手,防止入坑。
本篇只是入門(mén)級(jí)開(kāi)胃小菜,我最終用這個(gè)Service的目的是為了在我智能家居的項(xiàng)目中,手機(jī)端通過(guò)該AbilityService實(shí)時(shí)接收服務(wù)端推送過(guò)來(lái)的數(shù)據(jù),然后Service中接收到服務(wù)端推送過(guò)來(lái)的數(shù)據(jù)之后可以主動(dòng)更新UI對(duì)應(yīng)的Ability中的數(shù)據(jù),即需要打通Service主動(dòng)向Activity中傳遞數(shù)據(jù)這個(gè)關(guān)鍵技術(shù)點(diǎn)。詳細(xì)打通流程會(huì)在下篇文章中講解,這個(gè)是目前官網(wǎng)上面沒(méi)有的內(nèi)容。
??想了解更多關(guān)于開(kāi)源的內(nèi)容,請(qǐng)?jiān)L問(wèn):??