Ability与ServiceExtensionAbility通信
介绍
本示例展示通过[IDL的方式]和 [@ohos.rpc] 等接口实现了Ability与ServiceExtensionAbility之间的通信。
效果预览
使用说明
1.启动应用后,首页展示城市的天气信息,当前温度每隔5S会刷新一次。
工程目录
entry/src/main/ets/
|---Application
|---feature
| |---HomeFeature.ets // 任务信息组件
|---MainAbility
|---Mock
| |---RequestData.ts // 远程请求的数据
| |---WeatherData.ts // 天气页面数据
|---model
| |---FormDate.ts // 日期函数方法
| |---Main.ts // 数据类
|---pages
| |---home
| | |---BasicDataSource.ets // 懒加载封装类
| | |---HomeContent.ets // 内容组件
| | |---HoursWeather.ets // 天气组件(小时)
| | |---IndexHeader.ets // 首页头部组件
| | |---MultiDayWeather.ets // 天气组件(天)
| |---Home.ets // 首页
|---util
| |---Logger.ts // 日志工具
| |---Style.ts // 静态样式变量
具体实现
-
Ability与ServiceExtensionAbility通信的方法主要封装在idl_weather_service_proxy、idl_weather_service_stub、HomeFeature、ServiceExtAbility中。
-
源码参考:[idl_weather_service_proxy.ts]
/*
-
Copyright (c) 2022 Huawei Device Co., Ltd.
-
Licensed under the Apache License, Version 2.0 (the "License");
-
you may not use this file except in compliance with the License.
-
You may obtain a copy of the License at
-
http://www.apache.org/licenses/LICENSE-2.0
-
Unless required by applicable law or agreed to in writing, software
-
distributed under the License is distributed on an "AS IS" BASIS,
-
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-
See the License for the specific language governing permissions and
-
limitations under the License.
*/
import rpc from '@ohos.rpc'
import { updateWeatherCallback } from './i_idl_weather_service'
import IIdlWeatherService from './i_idl_weather_service'
import Logger from '../../../util/Logger'
export default class IdlWeatherServiceProxy implements IIdlWeatherService {
constructor(proxy) { this.proxy = proxy } updateWeather(data: number, callback: updateWeatherCallback): void { let _option = new rpc.MessageOption(0) let _data = new rpc.MessageParcel() let _reply = new rpc.MessageParcel() _data.writeInt(data) this.proxy.sendRequest(IdlWeatherServiceProxy.COMMAND_UPDATE_WEATHER, _data, _reply, _option).then(function (result) { if (result.errCode === 0) { let _errCode = result.reply.readInt() if (_errCode != 0) { let _returnValue = undefined callback(_errCode, _returnValue) return } let _returnValue = result.reply.readInt() callback(_errCode, _returnValue) } else { Logger.error("sendRequest failed, errCode: " + result.errCode) } }) } static readonly COMMAND_UPDATE_WEATHER = 1 private proxy
}
-
-
[idl_weather_service_stub.ts]
/*
-
Copyright (c) 2022 Huawei Device Co., Ltd.
-
Licensed under the Apache License, Version 2.0 (the "License");
-
you may not use this file except in compliance with the License.
-
You may obtain a copy of the License at
-
http://www.apache.org/licenses/LICENSE-2.0
-
Unless required by applicable law or agreed to in writing, software
-
distributed under the License is distributed on an "AS IS" BASIS,
-
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-
See the License for the specific language governing permissions and
-
limitations under the License.
*/
import rpc from '@ohos.rpc'
import { updateWeatherCallback } from './i_idl_weather_service'
import IIdlWeatherService from './i_idl_weather_service'
import Logger from '../../../util/Logger'
export default class IdlWeatherServiceStub extends rpc.RemoteObject implements IIdlWeatherService {
constructor(des: string) { super(des) } onRemoteRequest(code: number, data, reply, option): boolean { Logger.info("onRemoteRequest called, code = " + code) switch (code) { case IdlWeatherServiceStub.COMMAND_UPDATE_WEATHER: { let _data = data.readInt() this.updateWeather(_data, (errCode, returnValue) => { reply.writeInt(errCode) if (errCode == 0) { reply.writeInt(returnValue) } }) return true } default: { Logger.error("invalid request code" + code) break } } return false } updateWeather(data: number, callback: updateWeatherCallback): void { } static readonly COMMAND_UPDATE_WEATHER = 1
}
-
-
[HomeFeature]
/*
-
Copyright (c) 2022 Huawei Device Co., Ltd.
-
Licensed under the Apache License, Version 2.0 (the "License");
-
you may not use this file except in compliance with the License.
-
You may obtain a copy of the License at
-
http://www.apache.org/licenses/LICENSE-2.0
-
Unless required by applicable law or agreed to in writing, software
-
distributed under the License is distributed on an "AS IS" BASIS,
-
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-
See the License for the specific language governing permissions and
-
limitations under the License.
*/
import Logger from '../util/Logger'
import IdlWeatherServiceProxy from '../MainAbility/data/IIdlWeatherServiceTS/idl_weather_service_proxy'
const BUNDLE_NAME = "com.example.abilityconnectserviceextension"
const SERVICE_EXTENSION_ABILITY_NAME = "ServiceExtAbility"
const ERROR_CODE = -1 // 失败
const SUCCESS_CODE = 0 // 成功
export default class HomeFeature {
connection = -1 // 初始值 remoteCallback = null context = null options = null constructor(context) { this.context = context this.options = { outObj: this, // 连接成功时回调 onConnect: function (elementName, proxy) { Logger.info(`onConnect success`) // 接收来自服务返回的实例 let weatherProxy = new IdlWeatherServiceProxy(proxy) weatherProxy.updateWeather(123, this.outObj.remoteCallback) }, onDisconnect: function () { Logger.info(`onDisconnect`) }, onFailed: function () { Logger.info(`onFailed`) } } } connectServiceExtAbility(callback) { Logger.info(`connectServiceExtAbility`) this.remoteCallback = callback let want = { bundleName: BUNDLE_NAME, abilityName: SERVICE_EXTENSION_ABILITY_NAME } this.connection = this.context.connectAbility(want, this.options) Logger.info(`connectServiceExtAbility result:${this.connection}`) } disconnectServiceExtAbility(callback) { Logger.info(`disconnectServiceExtAbility`) this.context.disconnectAbility(this.connection).then((data) => { Logger.info(`disconnectAbility success:${JSON.stringify(data)}`) callback(SUCCESS_CODE) }).catch((error) => { Logger.error(`disconnectAbility failed:${JSON.stringify(error)}`) callback(ERROR_CODE) }) }
}
-
-
[ServiceExtAbility]
/*
-
Copyright (c) 2022 Huawei Device Co., Ltd.
-
Licensed under the Apache License, Version 2.0 (the "License");
-
you may not use this file except in compliance with the License.
-
You may obtain a copy of the License at
-
http://www.apache.org/licenses/LICENSE-2.0
-
Unless required by applicable law or agreed to in writing, software
-
distributed under the License is distributed on an "AS IS" BASIS,
-
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-
See the License for the specific language governing permissions and
-
limitations under the License.
*/
import ServiceExtension from '@ohos.app.ability.ServiceExtensionAbility'
import IdlWeatherServiceStub from '../MainAbility/data/IIdlWeatherServiceTS/idl_weather_service_stub'
import { updateWeatherCallback } from "../MainAbility/data/IIdlWeatherServiceTS/i_idl_weather_service"
import { getUpdateTemperature } from '../mock/RequestData'
import Logger from '../util/Logger'
class WeatherServiceStub extends IdlWeatherServiceStub {
constructor(des) { super(des) } updateWeather(data: number, callback: updateWeatherCallback): void { let temperature = getUpdateTemperature() callback(0, temperature) Logger.info(`testIntTransaction: temperature: ${temperature}`) }
}
export default class ServiceExtAbility extends ServiceExtension {
onCreate(want) { Logger.info(`onCreate, want: ${want.abilityName}`) } onRequest(want, startId) { Logger.info(`onRequest, want: ${want.abilityName}`) } onConnect(want) { Logger.info(`onConnect , want: ${want.abilityName}`) return new WeatherServiceStub("weather service stub") } onDisconnect(want) { Logger.info(`onDisconnect, want: ${want.abilityName}`) } onDestroy() { Logger.info(`onDestroy`) }
}
-
-
建立服务器连接:通过HomeFeature中的this.context.connectAbility(want, this.options)方法来建立服务器连接;
-
接收服务端实例并发送请求:连接成功时new IdlWeatherServiceProxy(proxy)来接收服务端实例,通过[@ohos.rpc] 接口来执行new rpc.MessageOption(0)、 new rpc.MessageParcel()、 new rpc.MessageParcel()获取 MessageParcel对象和请求的模式,调用idl_weather_service_proxy中的this.proxy.sendRequest()来发送请求;
-
接收远程请求处理数据:在idl_weather_service_stub中接收远程请求并通过ServiceExtAbility中的updateWeather()函数来处理数据进行返回;
-
获取数据:最后将获得的数据渲染到页面中去;
-
断开连接:可以通过HomeFeature中的this.context.disconnectAbility(this.connection)方法来断开服务器连接,这里的this.connection是建立连接之后的返回值。