HarmonyOS學習路之開發篇——Service Ability

Service Ability

Service Ability基本概念

基於Service模板的Ability(如下簡稱「Service」)主要用於後臺運行任務(如執行音樂播放、文件下載等),但不提供用戶交互界面。Service可由其餘應用或Ability啓動,即便用戶切換到其餘應用,Service仍將在後臺繼續運行。java

Service是單實例的。在一個設備上,相同的Service只會存在一個實例。若是多個Ability共用這個實例,只有當與Service綁定的全部Ability都退出後,Service纔可以退出。因爲Service是在主線程裏執行的,所以,若是在Service裏面的操做時間過長,開發者必須在Service裏建立新的線程來處理,防止形成主線程阻塞,應用程序無響應。json

建立Service

介紹如何建立一個Service。 一、建立Ability的子類,實現Service相關的生命週期方法。Service也是一種Ability,Ability爲Service提供瞭如下生命週期方法,經過重寫這些方法,來添加其餘Ability請求與Service Ability交互時的處理方法。緩存

  • onStart() 該方法在建立Service的時候調用,用於Service的初始化。在Service的整個生命週期只會調用一次,調用時傳入的Intent應爲空。
  • onCommand() 在Service建立完成以後調用,該方法在客戶端每次啓動該Service時都會調用,用戶能夠在該方法中作一些調用統計、初始化類的操做。
  • onConnect​() 在Ability和Service鏈接時調用,該方法返回IRemoteObject對象,用戶能夠在該回調函數中生成對應Service的IPC通訊通道,以便Ability與Service交互。Ability能夠屢次鏈接同一個Service,系統會緩存該Service的IPC通訊對象,只有第一個客戶端鏈接Service時,系統纔會調用Service的onConnect方法來生成IRemoteObject對象,然後系統會將同一個RemoteObject對象傳遞至其餘鏈接同一個Service的全部客戶端,而無需再次調用onConnect方法。
  • onDisconnect​() 在Ability與綁定的Service斷開鏈接時調用。
  • onStop() 在Service銷燬時調用。Service應經過實現此方法來清理任何資源,如關閉線程、註冊的偵聽器等。 建立Service的代碼示例以下:
public class ServiceAbility extends Ability {
    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
    }

    @Override
    public void onCommand(Intent intent, boolean restart, int startId) {
        super.onCommand(intent, restart, startId);
    }

    @Override
    public IRemoteObject onConnect(Intent intent) {
        return super.onConnect(intent);
    }

    @Override
    public void onDisconnect(Intent intent) {
        super.onDisconnect(intent);
    }

    @Override
    public void onStop() {
        super.onStop();
    }
}

二、註冊Service。 Service也須要在應用配置文件中進行註冊,註冊類型type須要設置爲service。dom

{
    "module": {
        "abilities": [         
            {    
                "name": ".ServiceAbility",
                "type": "service",
                "visible": true
                ...
            }
        ]
        ...
    }
    ...
}

啓動Service

介紹經過startAbility()啓動Service以及對應的中止方法。分佈式

  • 啓動Service Ability爲開發者提供了startAbility()方法來啓動另一個Ability。由於Service也是Ability的一種,開發者一樣能夠經過將Intent傳遞給該方法來啓動Service。不只支持啓動本地Service,還支持啓動遠程Service。 開發者能夠經過構造包含DeviceId、BundleName與AbilityName的Operation對象來設置目標Service信息。這三個參數的含義以下:
    • DeviceId:表示設備ID。若是是本地設備,則能夠直接留空;若是是遠程設備,能夠經過ohos.distributedschedule.interwork.DeviceManager提供的getDeviceList獲取設備列表,詳見《API參考》。
    • BundleName:表示包名稱。
    • AbilityName:表示待啓動的Ability名稱。

啓動本地設備Service的代碼示例以下:ide

Intent intent = new Intent();
Operation operation = new Intent.OperationBuilder()
        .withDeviceId("")
        .withBundleName("com.domainname.hiworld.himusic")
        .withAbilityName("com.domainname.hiworld.himusic.ServiceAbility")
        .build();
intent.setOperation(operation);
startAbility(intent);

啓動遠程設備Service的代碼示例以下:函數

Intent intent = new Intent();
Operation operation = new Intent.OperationBuilder()
        .withDeviceId("deviceId")
        .withBundleName("com.domainname.hiworld.himusic")
        .withAbilityName("com.domainname.hiworld.himusic.ServiceAbility")
        .withFlags(Intent.FLAG_ABILITYSLICE_MULTI_DEVICE) // 設置支持分佈式調度系統多設備啓動的標識
        .build();
intent.setOperation(operation);
startAbility(intent);

執行上述代碼後,Ability將經過startAbility() 方法來啓動Service。ui

  • 若是Service還沒有運行,則系統會先調用onStart()來初始化Service,再回調Service的onCommand()方法來啓動Service。線程

  • 若是Service正在運行,則系統會直接回調Service的onCommand()方法來啓動Service。rest

  • 中止Service Service一旦建立就會一直保持在後臺運行,除非必須回收內存資源,不然系統不會中止或銷燬Service。開發者能夠在Service中經過terminateAbility()中止本Service或在其餘Ability調用stopAbility()來中止Service。 中止Service一樣支持中止本地設備Service和中止遠程設備Service,使用方法與啓動Service同樣。一旦調用中止Service的方法,系統便會盡快銷燬Service。

鏈接Service

若是Service須要與Page Ability或其餘應用的Service Ability進行交互,則須建立用於鏈接的Connection。Service支持其餘Ability經過connectAbility()方法與其進行鏈接。

在使用connectAbility()處理回調時,須要傳入目標Service的Intent與IAbilityConnection的實例。IAbilityConnection提供了兩個方法供開發者實現:onAbilityConnectDone()是用來處理鏈接Service成功的回調,onAbilityDisconnectDone()是用來處理Service異常死亡的回調。

建立鏈接Service回調實例的代碼示例以下:

// 建立鏈接Service回調實例
private IAbilityConnection connection = new IAbilityConnection() {
    // 鏈接到Service的回調
    @Override
    public void onAbilityConnectDone(ElementName elementName, IRemoteObject iRemoteObject, int resultCode) {
        // Client側須要定義與Service側相同的IRemoteObject實現類。開發者獲取服務端傳過來IRemoteObject對象,並從中解析出服務端傳過來的信息。
    }

    // Service異常死亡的回調
    @Override
    public void onAbilityDisconnectDone(ElementName elementName, int resultCode) {
    }
};

鏈接Service的代碼示例以下:

// 鏈接Service
Intent intent = new Intent();
Operation operation = new Intent.OperationBuilder()
        .withDeviceId("deviceId")
        .withBundleName("com.domainname.hiworld.himusic")
        .withAbilityName("com.domainname.hiworld.himusic.ServiceAbility")
        .build();
intent.setOperation(operation);
connectAbility(intent, connection);

同時,Service側也須要在onConnect()時返回IRemoteObject,從而定義與Service進行通訊的接口。onConnect()須要返回一個IRemoteObject對象,HarmonyOS提供了IRemoteObject的默認實現,用戶能夠經過繼承LocalRemoteObject來建立自定義的實現類。Service側把自身的實例返回給調用側的代碼示例以下:

// 建立自定義IRemoteObject實現類
private class MyRemoteObject extends LocalRemoteObject {
    MyRemoteObject(){
    }
}

// 把IRemoteObject返回給客戶端
@Override
protected IRemoteObject onConnect(Intent intent) {
    return new MyRemoteObject();
}

Service Ability生命週期

與Page相似,Service也擁有生命週期,如圖1所示。根據調用方法的不一樣,其生命週期有如下兩種路徑:

  • 啓動Service 該Service在其餘Ability調用startAbility()時建立,而後保持運行。其餘Ability經過調用stopAbility()來中止Service,Service中止後,系統會將其銷燬。
  • 鏈接Service 該Service在其餘Ability調用connectAbility()時建立,客戶端可經過調用disconnectAbility​()斷開鏈接。多個客戶端能夠綁定到相同Service,並且當全部綁定所有取消後,系統即會銷燬該Service。

圖1 Service生命週期 在這裏插入圖片描述

前臺Service

通常狀況下,Service都是在後臺運行的,後臺Service的優先級都是比較低的,當資源不足時,系統有可能回收正在運行的後臺Service。

在一些場景下(如播放音樂),用戶但願應用可以一直保持運行,此時就須要使用前臺Service。前臺Service會始終保持正在運行的圖標在系統狀態欄顯示。

使用前臺Service並不複雜,開發者只需在Service建立的方法裏,調用keepBackgroundRunning()將Service與通知綁定。調用keepBackgroundRunning()方法前須要在配置文件中聲明ohos.permission.KEEP_BACKGROUND_RUNNING權限,同時還須要在配置文件中添加對應的backgroundModes參數。在onStop()方法中調用cancelBackgroundRunning​()方法可中止前臺Service。

使用前臺Service的onStart()代碼示例以下:

// 建立通知,其中1005爲notificationId
NotificationRequest request = new NotificationRequest(1005);
NotificationRequest.NotificationNormalContent content = new NotificationRequest.NotificationNormalContent();
content.setTitle("title").setText("text");
NotificationRequest.NotificationContent notificationContent = new NotificationRequest.NotificationContent(content);
request.setContent(notificationContent);

// 綁定通知,1005爲建立通知時傳入的notificationId
keepBackgroundRunning(1005, request);

在配置文件中,「module > abilities」字段下對當前Service作以下配置:

{    
    "name": ".ServiceAbility",
    "type": "service",
    "visible": true,
    "backgroundModes": ["dataTransfer", "location"]
}
相關文章
相關標籤/搜索