背景
双方模块进行交互,如果一方挂掉了,另一方还如痴如醉地一直为它工作,显然是有悖常理的。一旦对方不幸结束了,我们如何感知到并且正常开展后续工作?本文综合了 Sensors,msdp 模块进行了详实的介绍,希望对小伙们的此类工作有所帮助。
以下实例全部基于"client,proxy→stub,service"架构。
目录
1.原理介绍
2.几种情况的重点说明
2.1 例 1:服务侧监听客户侧消亡
2.2 例 2:客户端监听服务端消亡
2.3 例 3:服务端监听客户端消亡
2.4 例 4:服务端监听底层 HDI 侧消亡
3. 传感器服务端监听不同客户端消亡的处理实例
4.小结
一、原理介绍
1. HarmonyOS 远端状态订阅开发实例
IPC/RPC 提供对远端 Stub 对象状态的订阅机制, 在远端 Stub 对象消亡时,可触发消亡通知告诉本地 Proxy 对象。这种状态通知订阅需要调用特定接口完成,当不再需要订阅时也需要调用特定接口取消。使用这种订阅机制的用户,需要实现消亡通知接口 DeathRecipient 并实现 onRemoteDied 方法清理资源。该方法会在远端 Stub 对象所在进程消亡时被回调。值得注意的是,调用这些接口有一定的顺序。首先,需要 Proxy 订阅 Stub 消亡通知,若在订阅期间 Stub 状态正常,则在不再需要时取消订阅;若在订阅期间 Stub 所在进程退出,则会自动触发 Proxy 自定义的后续操作。
2. 使用场景
这种订阅机制适用于本地 Proxy 对象需要感知远端 Stub 对象所在进程消亡。当 Proxy 感知到 Stub 端消亡后,可适当清理本地资源。此外,RPC 目前不提供匿名 Stub 对象的消亡通知,即只有向 SAMgr 注册过的服务才能被订阅消亡通知,IPC 则支持匿名对象的消亡通知。
3. Native 侧接口
4. 调用序列图
二、几种情况的重点说明
为了方便阅读和理解,名称有所修改,无关的代码被删除。远端(被监听)是消亡的一侧,本端是处理消亡的一侧。本端既可以在客户侧,也可以在服务侧。一般本端在客户侧是用来监听服务侧消亡情况,在服务侧是用来监听客户侧消亡的情况,或者底层提供服务侧的消亡情况。
只要出现 OnRemoteDied() 的地方就是本端,它是用来处理消亡的地方。
例 1:服务侧监听客户侧消亡
在服务侧创建消亡信息接收者对象,添加、删除监听,以及消亡响应处理忽略,着重看一下客户侧如何将被监听的对象一路传递到服务侧的。
在远端要做的事情
步骤 1. 定义被监听者类 ClientStubObject
class IRemoteClientObject : public IRemoteBroker {
public:
DECLARE_INTERFACE_DESCRIPTOR(u"ohos.xxx.IRemoteClientObject");// 必须存在,不然找不到该对象
};
class ClientStubObject : public IRemoteStub<IRemoteClientObject> {
public:
explicit ClientStubObject(napi_env env) : env_(env) {}
virtual ~ClientStubObject() {};
int32_t OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override;
};
步骤 2. 创建被监听者类对象
sptr<IRemoteClientObject> object = new (std::nothrow) ClientStubObject(env);
步骤 3. 把 object 一路传递给服务侧
void DeviceStatusSrvProxy::Subscribe(sptr<IRemoteClientObject> object)
{
sptr<IRemoteObject> remote = Remote();
MessageParcel data;
WRITEREMOTEOBJECT(data, object->AsObject());
MessageParcel reply;
MessageOption option;
int32_t ret = remote->SendRequest(static_cast<uint32_t>(DeviceInterfaceCode::DEVICESTATUS_SUBSCRIBE),
data, reply, option);
}
int32_t DeviceStatusSrvStub::SubscribeStub(MessageParcel &data, MessageParcel &reply)
{
sptr<IRemoteObject> obj = data.ReadRemoteObject();
sptr<IRemoteClientObject> object = iface_cast<IRemoteClientObject>(obj);
return RET_OK;
}
例 2:客户端监听服务端消亡
此种情况处理较为简单, 全部代码在客户侧(本端)实现。