HarmonyOS4.0系统性深入开发23ServiceAbility组件概述

发布时间:2024年01月19日

ServiceAbility组件概述

ServiceAbility,即"基于Service模板的Ability",主要用于后台运行任务(如执行音乐播放、文件下载等),不提供用户交互界面。ServiceAbility可由其他应用或PageAbility启动,即使用户切换到其他应用,ServiceAbility仍将在后台继续运行。

ServiceAbility组件配置

与PageAbility类似,ServiceAbility的相关配置在config.json配置文件的"module"对象的"abilities"对象中,与PageAbility的区别在于"type"属性及"backgroundModes"属性。

表1 ServiceAbility部分配置项说明

属性名称含义数据类型是否可缺省
type表示Ability的类型。取值为"service"时表示该Ability是基于Service模板开发的Ability。字符串
backgroundModes表示后台服务的类型,可以为一个服务配置多个后台服务类型。该标签仅适用于service类型的Ability。取值范围如下:dataTransfer:通过网络/对端设备进行数据下载、备份、分享、传输等业务。audioPlayback:音频输出业务。audioRecording:音频输入业务。pictureInPicture:画中画、小窗口播放视频业务。voip:音视频电话、VOIP业务。location:定位、导航业务。bluetoothInteraction:蓝牙扫描、连接、传输业务。wifiInteraction:WLAN扫描、连接、传输业务。screenFetch:录屏、截屏业务。multiDeviceConnection:多设备互联业务。字符串数组可缺省,缺省值为空。

ServiceAbility支持的配置项及详细说明详见module对象内部结构

ServiceAbility的生命周期

开发者可以根据业务场景重写生命周期相关接口。ServiceAbility生命周期接口说明见下表。

表1 ServiceAbility生命周期接口说明

接口名描述
onStart(): void该方法在创建ServiceAbility的时候调用,用于Service的初始化,在ServiceAbility的整个生命周期只会调用一次。
onCommand(want: Want, startId: number): void在Service创建完成之后调用,该方法在客户端每次启动该Service时都会调用,开发者可以在该方法中做一些调用统计、初始化类的操作。
onConnect(want: Want): rpc.RemoteObject在连接ServiceAbility时调用。
onDisconnect(want: Want): void在与已连接的ServiceAbility断开连接时调用。
onStop(): void在ServiceAbility销毁时调用。开发者应通过实现此方法来清理资源,如关闭线程、注册的侦听器等。

创建ServiceAbility

  1. 创建ServiceAbility。

    重写ServiceAbility的生命周期方法,添加其他Ability请求与ServiceAbility交互时的处理方法。

      import rpc from "@ohos.rpc"
      
      class FirstServiceAbilityStub extends rpc.RemoteObject {
        constructor(des: any) {
          if (typeof des === 'string') {
            super(des)
          } else {
            return
          }
        }
      }
      
      export default {
        onStart() {
          console.info('ServiceAbility onStart')
        },
        onStop() {
          console.info('ServiceAbility onStop')
        },
        onCommand(want, startId) {
          console.info('ServiceAbility onCommand')
        },
        onConnect(want) {
          console.info('ServiceAbility onConnect' + want)
          return new FirstServiceAbilityStub('test')
        },
        onDisconnect(want) {
          console.info('ServiceAbility onDisconnect' + want)
        }
      }
    
  2. 注册ServiceAbility。

    ServiceAbility需要在应用配置文件config.json中进行注册,注册类型type需要设置为service。"visible"属性表示ServiceAbility是否可以被其他应用调用,true表示可以被其他应用调用,false表示不能被其他应用调用(仅应用内可以调用)。若ServiceAbility需要被其他应用调用,注册ServiceAbility时需要设置"visible"为true,同时需要设置支持关联启动。

         {
           "module": {
             "abilities": [
               {
                 "name": ".ServiceAbility",
                 "srcLanguage": "ets",
                 "srcPath": "ServiceAbility",
                 "icon": "$media:icon",
                 "description": "hap sample empty service",
                 "type": "service",
                 "visible": true
               }
             ]
           }
         }
    

启动ServiceAbility

ServiceAbility的启动与其他Ability并无区别,应用开发者可以在PageAbility中通过featureAbility的startAbility接口拉起ServiceAbility,在ServiceAbility中通过particleAbility的startAbility接口拉起ServiceAbility。

如下示例展示了在PageAbility中通过startAbility启动bundleName为"com.example.myapplication",abilityName为"ServiceAbility"的ServiceAbility的方法。启动FA模型的ServiceAbility时,需要在abilityName前拼接bundleName字符串。

import featureAbility from '@ohos.ability.featureAbility'

async function startServiceAbility() {
  try {
    console.info('Begin to start ability')
    let param = {
      want: {
        bundleName: "com.example.myapplication",
        abilityName: "com.example.myapplication.ServiceAbility"
      }
    }
    await featureAbility.startAbility(param)
    console.info(`Start ability succeed`)
  } catch (error) {
    console.error('Start ability failed with ' + error)
  }
}

执行上述代码后,Ability将通过startAbility() 方法来启动ServiceAbility。

  • 如果ServiceAbility尚未运行,则系统会先调用onStart()来初始化ServiceAbility,再回调Service的onCommand()方法来启动ServiceAbility。
  • 如果ServiceAbility正在运行,则系统会直接回调ServiceAbility的onCommand()方法来启动ServiceAbility。

连接ServiceAbility

如果ServiceAbility需要与PageAbility或其他应用的ServiceAbility进行交互,则须创建用于连接的Connection。ServiceAbility支持其他Ability通过connectAbility()方法与其进行连接。PageAbility的connectAbility方法定义在featureAbility中,ServiceAbility的connectAbility方法定义在particleAbility中。在使用connectAbility()处理回调时,需要传入目标Service的Want与IAbilityConnection的实例。IAbilityConnection提供了以下方法供开发者实现。

表1 IAbilityConnection接口说明

接口名描述
onConnect()用于处理连接Service成功的回调。
onDisconnect()用来处理Service异常死亡的回调。
onFailed()用来处理连接Service失败的回调。

PageAbility创建连接本地ServiceAbility回调实例的代码以及连接本地ServiceAbility的示例代码如下:

import rpc from "@ohos.rpc"
import prompt from '@system.prompt'
import featureAbility from '@ohos.ability.featureAbility'

let option = {
  onConnect: function onConnectCallback(element, proxy) {
    console.info(`onConnectLocalService onConnectDone`)
    if (proxy === null) {
      prompt.showToast({
        message: "Connect service failed"
      })
      return
    }
    let data = rpc.MessageParcel.create()
    let reply = rpc.MessageParcel.create()
    let option = new rpc.MessageOption()
    data.writeInterfaceToken("connect.test.token")
    proxy.sendRequest(0, data, reply, option)
    prompt.showToast({
      message: "Connect service success"
    })
  },
  onDisconnect: function onDisconnectCallback(element) {
    console.info(`onConnectLocalService onDisconnectDone element:${element}`)
    prompt.showToast({
      message: "Disconnect service success"
    })
  },
  onFailed: function onFailedCallback(code) {
    console.info(`onConnectLocalService onFailed errCode:${code}`)
    prompt.showToast({
      message: "Connect local service onFailed"
    })
  }
}

let request = {
  bundleName: "com.example.myapplication",
  abilityName: "com.example.myapplication.ServiceAbility",
}
let connId = featureAbility.connectAbility(request, option)

同时,Service侧也需要在onConnect()时返回IRemoteObject,从而定义与Service进行通信的接口。onConnect()需要返回一个IRemoteObject对象。HarmonyOS提供了IRemoteObject的默认实现,开发者可以通过继承rpc.RemoteObject来创建自定义的实现类。

Service侧把自身的实例返回给调用侧的示例代码如下:

import rpc from "@ohos.rpc"

class FirstServiceAbilityStub extends rpc.RemoteObject {
  constructor(des: any) {
    if (typeof des === 'string') {
      super(des)
    } else {
      return
    }
  }

  onRemoteRequest(code: number, data: any, reply: any, option: any) {
    console.info(`onRemoteRequest called`)
    if (code === 1) {
      let string = data.readString()
      console.info(`string=${string}`)
      let result = Array.from(string).sort().join('')
      console.info(`result=${result}`)
      reply.writeString(result)
    } else {
      console.info(`unknown request code`)
    }
    return true
  }
}
文章来源:https://blog.csdn.net/qq_46189388/article/details/135689116
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。