HarmonyOS Sample 之 ServiceAbility 跨设备接口调用 原创 精华

Buty9147
发布于 2021-7-1 21:51
浏览
1收藏

@toc

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文件
HarmonyOS Sample 之 ServiceAbility 跨设备接口调用-鸿蒙开发者社区

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文件,生成对应的接口类、桩类和代理类

HarmonyOS Sample 之 ServiceAbility 跨设备接口调用-鸿蒙开发者社区 HarmonyOS Sample 之 ServiceAbility 跨设备接口调用-鸿蒙开发者社区

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);

效果展示

前台Service IPC/RPC调用
HarmonyOS Sample 之 ServiceAbility 跨设备接口调用-鸿蒙开发者社区 HarmonyOS Sample 之 ServiceAbility 跨设备接口调用-鸿蒙开发者社区

完整代码

附件直接下载。

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
ServiceAbility.zip 1.39M 33次下载
已于2021-7-1 22:00:18修改
2
收藏 1
回复
举报
2条回复
按时间正序
/
按时间倒序
mb609898e2cfb86
mb609898e2cfb86

代码和演示都很详细,感谢楼主分享。

回复
2021-7-2 10:02:15
Buty9147
Buty9147 回复了 mb609898e2cfb86
代码和演示都很详细,感谢楼主分享。

共同学习,希望对大家也能有一点点帮助!

回复
2021-7-4 14:43:28
回复
    相关推荐