ServiceAbility 跨设备接口调用
介绍
本示例演示了Service Ability的启动、停止、连接、断开连接等操作,支持对跨设备的Service Ability进行操作。
你将学会以下三个知识点:
1.IDL的使用,以及IPC方法的调用
2.前台Service的使用方法
3.EventHandle事件处理的使用方法
搭建环境
安装DevEco Studio,详情请参考DevEco Studio下载。
设置DevEco Studio开发环境,DevEco Studio开发环境需要依赖于网络环境,需要连接上网络才能确保工具的正常使用,可以根据如下两种情况来配置开发环境:
- 如果可以直接访问Internet,只需进行下载HarmonyOS SDK操作。
- 如果网络不能直接访问Internet,需要通过代理服务器才可以访问,请参考配置开发环境。
代码结构解读
后台逻辑
- │ config.json #全局配置文件
- │
- ├─idl
- │ └─ohos
- │ └─samples
- │ └─serviceability
- │ IRemoteAgent.idl #提供远程接口idl文件
- │
- ├─java
- │ └─ohos
- │ └─samples
- │ └─serviceability
- │ │ ForegroundServiceAbility.java #前台Service Ability
- │ │ LocalServiceAbility.java #模拟本地的Service Ability
- │ │ MainAbility.java
- │ │ RemoteAbility.java #模拟远端的Service Ability
- │ │
- │ └─slice
- │ MainAbilitySlice.java #主能力页
页面布局文件只有一个 main_slice.xml
页面布局
三个知识点
1.IDL的使用,以及IPC方法的调用
术语:
当客户端和服务器通信时,需要定义双方都认可的接口,以保障双方可以成功通信,HarmonyOS IDL(HarmonyOS Interface Definition Language)则是一种定义此类接口的工具。
跨进程调用(IPC)inter-process communication 或 跨设备调用(RPC)remote procedure call
IDL接口使用规范:
https://developer.harmonyos.com/cn/docs/documentation/doc-references/idl-overview-0000001050762835
先声明权限,同时敏感权限还需要请求用户授权,前几篇都有写过这里就不写了。
- "reqPermissions": [
- {
- "name": "ohos.permission.GET_DISTRIBUTED_DEVICE_INFO"
- },
- ...
- {
- "name": "ohos.permission.DISTRIBUTED_DATASYNC"
- }
- ]
a.创建.idl文件
IRemoteAgent.idl
- // Declare any non-default types here with sequenceable or interface statements
- interface ohos.samples.serviceability.IRemoteAgent {
- /*
- * Demo service method use some parameters
- */
- void setRemoteObject([in] String param);
- }
b.编译idl文件,生成对应的接口类、桩类和代理类
c.服务端IDL的实现
- private static final String DESCRIPTOR = "ohos.samples.serviceability.RemoteAbility";
- //idl的服务端实现,
- RemoteAgentStub remoteAgentStub = new RemoteAgentStub(DESCRIPTOR) {
- @Override
- public void setRemoteObject(String param) {
- HiLog.info(LABEL_LOG, "%{public}s", "setRemoteObject:"+param);
- //不能这样,要用下面通知的方式
- //showTips(RemoteAbility.this, param);
- //赋值
- param_mess=param;
- //事件通知
- eventHandler.sendEvent(EVENT_ABILITY_MESS);
- }
- };
d.客户端调用IPC方法
- //IDL代理类
- private RemoteAgentProxy remoteAgentProxy;
- /**
- * 连接 Service
- * @param isConnectRemote
- */
- private void connectService(boolean isConnectRemote) {
- //三元表达式,判断连接本地还是远端Service
- Intent intent = isConnectRemote
- ? getRemoteServiceIntent(REMOTE_BUNDLE, REMOTE_SERVICE)
- : getLocalServiceIntent(LOCAL_BUNDLE, NORMAL_SERVICE);
- //连接 Service
- boolean isConnect=connectAbility(intent,connection);
- if (isConnect && remoteAgentProxy!=null) {
- try {
- //调用服务端IPC方法
- remoteAgentProxy.setRemoteObject("This param from client");
- } catch (RemoteException e) {
- HiLog.error(LABEL_LOG, "%{public}s", "onAbilityConnectDone RemoteException");
- }
- }
- }
- //建立连接,实例化代理对象
- private IAbilityConnection connection = new IAbilityConnection() {
- @Override
- public void onAbilityConnectDone(ElementName elementName, IRemoteObject iRemoteObject, int resultCode) {
- //发个通知,Service 连接成功了
- eventHandler.sendEvent(EVENT_ABILITY_CONNECT_DONE);
- //实例化代理对象
- remoteAgentProxy = new RemoteAgentProxy(iRemoteObject);
- }
- @Override
- public void onAbilityDisconnectDone(ElementName elementName, int resultCode) {
- //发个通知,Service 断开连接了,主动断开不会执行,关闭服务端会执行
- eventHandler.sendEvent(EVENT_ABILITY_DISCONNECT_DONE);
- }
- };
2.前台Service的使用方法
a.权限声明:
- "reqPermissions": [
- {
- "name": "ohos.permission.KEEP_BACKGROUND_RUNNING"
- },
- ...
- ]
b.设置通知栏内容,然后,
- 在onStart方法调用keepBackgroundRunning方法在后台保留此服务能力并显示通知栏。
- 在onStop方法调用cancelBackgroundRunning()方法取消此功能的后台运行以释放系统内存。
- //通知ID
- private static final int NOTIFICATION_ID = 0XD0000002;
- @Override
- protected void onStart(Intent intent) {
- //调用方法
- startForeground();
- super.onStart(intent);
- }
- @Override
- protected void onStop() {
- super.onStop();
- //取消此功能的后台运行以释放系统内存。
- cancelBackgroundRunning();
- }
- /**
- * 在后台保留此服务能力并显示通知栏。
- */
- private void startForeground() {
- HiLog.info(LABEL_LOG, "startForeground");
- //任务栏显示通知
- NotificationRequest request = new NotificationRequest(NOTIFICATION_ID).setTapDismissed(true);
- //
- NotificationRequest.NotificationNormalContent content = new NotificationRequest.NotificationNormalContent();
- content.setTitle("SD card存储卡已意外移除").setText("请先卸载存储卡,再将其移除,以防数据丢失");
- content.setAdditionalText("21分钟前");
- //设置通知栏内容
- NotificationRequest.NotificationContent notificationContent = new NotificationRequest.NotificationContent(content);
- request.setContent(notificationContent);
- //在后台保留此服务能力并显示通知栏。
- keepBackgroundRunning(NOTIFICATION_ID, request);
- }
3.EventHandle事件处理的使用方法
EventHandler 将事件或 Runnable 任务传递到线程的事件队列,并在事件或任务从事件队列中出来时执行。
您可以使用 EventHandler 在不同线程之间调度和处理事件和 Runnable 对象,并在一定的时间间隔内安排要处理的事件或 Runnable 对象。您可以使用此类中提供的方法发送同步或异步事件、延迟事件处理以及设置事件优先级。
- //定义事件ID
- private static final int EVENT_ABILITY_CONNECT_DONE = 0x1000001;
- private static final int EVENT_ABILITY_DISCONNECT_DONE = 0x1000002;
- private EventHandler eventHandler = new EventHandler(EventRunner.current()) {
- @Override
- protected void processEvent(InnerEvent event) {
- switch (event.eventId) {
- case EVENT_ABILITY_CONNECT_DONE:
- showTips(MainAbilitySlice.this, "Service connect succeeded");
- break;
- case EVENT_ABILITY_DISCONNECT_DONE:
- showTips(MainAbilitySlice.this, "Service disconnect succeeded");
- break;
- default:
- break;
- }
- }
- };
- //发个通知,Service 连接成功了
- eventHandler.sendEvent(EVENT_ABILITY_CONNECT_DONE);
效果展示
前台ServiceIPC/RPC调用
文章相关附件可以点击下面的原文链接前往下载
原文链接:https://harmonyos.51cto.com/posts/4776