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,務必弄明白》
工程創建完成之后,鼠標選擇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”,如下圖
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中通過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中傳遞數據這個關鍵技術點。詳細打通流程會在下篇文章中講解,這個是目前官網上面沒有的內容。
|