写点什么

HarmonyOS 远端状态订阅开发实例

  • 2023-10-12
    北京
  • 本文字数:2568 字

    阅读完需:约 8 分钟

HarmonyOS远端状态订阅开发实例

IPC/RPC 提供对远端 Stub 对象状态的订阅机制, 在远端 Stub 对象消亡时,可触发消亡通知告诉本地 Proxy 对象。这种状态通知订阅需要调用特定接口完成,当不再需要订阅时也需要调用特定接口取消。使用这种订阅机制的用户,需要实现消亡通知接口 DeathRecipient 并实现 onRemoteDied 方法清理资源。该方法会在远端 Stub 对象所在进程消亡或所在设备离开组网时被回调。值得注意的是,调用这些接口有一定的顺序。首先,需要 Proxy 订阅 Stub 消亡通知,若在订阅期间 Stub 状态正常,则在不再需要时取消订阅;若在订阅期间 Stub 所在进程退出或者所在设备退出组网,则会自动触发 Proxy 自定义的后续操作。

使用场景

这种订阅机制适用于本地 Proxy 对象需要感知远端 Stub 对象所在进程消亡,或所在设备离开组网的场景。当 Proxy 感知到 Stub 端消亡后,可适当清理本地资源。此外,RPC 目前不提供匿名 Stub 对象的消亡通知,即只有向 SAMgr 注册过的服务才能被订阅消亡通知,IPC 则支持匿名对象的消亡通知。

Native 侧接口

参考代码

#include "iremote_broker.h"#include "iremote_stub.h"

//定义消息码enum { TRANS_ID_PING_ABILITY = 5, TRANS_ID_REVERSED_MONITOR};
const std::string DESCRIPTOR = "test.ITestAbility";
class ITestService : public IRemoteBroker {public: // DECLARE_INTERFACE_DESCRIPTOR是必需的,入参需使用std::u16string; DECLARE_INTERFACE_DESCRIPTOR(to_utf16(DESCRIPTOR)); virtual int TestPingAbility(const std::u16string &dummy) = 0; // 定义业务函数};
class TestServiceProxy : public IRemoteProxy<ITestAbility> {public: explicit TestAbilityProxy(const sptr<IRemoteObject> &impl); virtual int TestPingAbility(const std::u16string &dummy) override; int TestAnonymousStub();private: static inline BrokerDelegator<TestAbilityProxy> delegator_; // 方便后续使用iface_cast宏};
TestServiceProxy::TestServiceProxy(const sptr<IRemoteObject> &impl) : IRemoteProxy<ITestAbility>(impl){}
int TestServiceProxy::TestPingAbility(const std::u16string &dummy){ MessageOption option; MessageParcel dataParcel, replyParcel; dataParcel.WriteString16(dummy); int error = PeerHolder::Remote()->SendRequest(TRANS_ID_PING_ABILITY, dataParcel, replyParcel, option); int result = (error == ERR_NONE) ? replyParcel.ReadInt32() : -1; return result;}
复制代码


#include "iremote_object.h"
class TestDeathRecipient : public IRemoteObject::DeathRecipient {public: virtual void OnRemoteDied(const wptr<IRemoteObject>& remoteObject);}
void TestDeathRecipient::OnRemoteDied(const wptr<IRemoteObject>& remoteObject){}
复制代码


sptr<IPCObjectProxy> object = new IPCObjectProxy(1, to_utf16(DESCRIPTOR));sptr<IRemoteObject::DeathRecipient> deathRecipient (new TestDeathRecipient());// 构造一个消亡通知对象bool result = object->AddDeathRecipient(deathRecipient); // 注册消亡通知result = object->RemoveDeathRecipient(deathRecipient); // 移除消亡通知
复制代码

JS 侧接口

参考代码

import FA from "@ohos.ability.featureAbility";let proxy;let connect = {    onConnect: function(elementName, remoteProxy) {        console.log("RpcClient: js onConnect called.");        proxy = remoteProxy;    },    onDisconnect: function(elementName) {        console.log("RpcClient: onDisconnect");    },    onFailed: function() {        console.log("RpcClient: onFailed");    }};let want = {    "bundleName": "com.ohos.server",    "abilityName": "com.ohos.server.MainAbility",};FA.connectAbility(want, connect);class MyDeathRecipient {    onRemoteDied() {        console.log("server died");    }}let deathRecipient = new MyDeathRecipient();proxy.addDeathRecipient(deathRecipient, 0);proxy.removeDeathRecipient(deathRecipient, 0);
复制代码

Stub 感知 Proxy 消亡(匿名 Stub 的使用)

正向的消亡通知是 Proxy 感知 Stub 的状态,若想达到反向的死消亡通知,即 Stub 感知 Proxy 的状态,可以巧妙的利用正向消亡通知。如两个进程 A(原 Stub 所在进程)和 B(原 Proxy 所在进程),进程 B 在获取到进程 A 的 Proxy 对象后,在 B 进程新建一个匿名 Stub 对象(匿名指未向 SAMgr 注册),可称之为回调 Stub,再通过 SendRequest 接口将回调 Stub 传给进程 A 的原 Stub。这样一来,进程 A 便获取到了进程 B 的回调 Proxy。当进程 B 消亡或 B 所在设备离开组网时,回调 Stub 会消亡,回调 Proxy 会感知,进而通知给原 Stub,便实现了反向消亡通知。


注意:

反向死亡通知仅限设备内跨进程通信使用,不可用于跨设备。

当匿名 Stub 对象没有被任何一个 Proxy 指向的时候,内核会自动回收。

参考代码

//Proxyint TestAbilityProxy::TestAnonymousStub(){    MessageOption option;    MessageParcel dataParcel, replyParcel;    dataParcel.UpdateDataVersion(Remote());    dataParcel.WriteRemoteObject(new TestAbilityStub());    int error = Remote()->SendRequest(TRANS_ID_REVERSED_MONITOR,dataParcel, replyParcel, option);    int result = (error == ERR_NONE) ? replyParcel.ReadInt32() : -1;    return result;}
//Stub
int TestAbilityStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option){ switch (code) { case TRANS_ID_REVERSED_MONITOR: { sptr<IRemoteObject> obj = data.ReadRemoteObject(); if (obj == nullptr) { reply.WriteInt32(ERR_NULL_OBJECT); return ERR_NULL_OBJECT; } bool result = obj->AddDeathRecipient(new TestDeathRecipient()); result ? reply.WriteInt32(ERR_NONE) : reply.WriteInt32(-1); break; } default: break; } return ERR_NONE;}
复制代码


用户头像

每一位开发者都是华为要汇聚的星星之火 2021-10-15 加入

提供HarmonyOS关键技术解析、版本更新、开发者实践和活动资讯,欢迎各位开发者加入HarmonyOS生态,一起创造无限可能!

评论

发布
暂无评论
HarmonyOS远端状态订阅开发实例_HarmonyOS开发者_InfoQ写作社区