• HarmonyOS 远端状态订阅开发实例


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

    使用场景

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

    Native 侧接口

    参考代码
     

    1. #include "iremote_broker.h"
    2. #include "iremote_stub.h"
    3. //定义消息码
    4. enum {
    5. TRANS_ID_PING_ABILITY = 5,
    6. TRANS_ID_REVERSED_MONITOR
    7. };
    8. const std::string DESCRIPTOR = "test.ITestAbility";
    9. class ITestService : public IRemoteBroker {
    10. public:
    11. // DECLARE_INTERFACE_DESCRIPTOR是必需的,入参需使用std::u16string
    12. DECLARE_INTERFACE_DESCRIPTOR(to_utf16(DESCRIPTOR));
    13. virtual int TestPingAbility(const std::u16string &dummy) = 0; // 定义业务函数
    14. };
    15. class TestServiceProxy : public IRemoteProxy<ITestAbility> {
    16. public:
    17. explicit TestAbilityProxy(const sptr<IRemoteObject> &impl);
    18. virtual int TestPingAbility(const std::u16string &dummy) override;
    19. int TestAnonymousStub();
    20. private:
    21. static inline BrokerDelegator<TestAbilityProxy> delegator_; // 方便后续使用iface_cast宏
    22. };
    23. TestServiceProxy::TestServiceProxy(const sptr<IRemoteObject> &impl)
    24. : IRemoteProxy<ITestAbility>(impl)
    25. {
    26. }
    27. int TestServiceProxy::TestPingAbility(const std::u16string &dummy){
    28. MessageOption option;
    29. MessageParcel dataParcel, replyParcel;
    30. dataParcel.WriteString16(dummy);
    31. int error = PeerHolder::Remote()->SendRequest(TRANS_ID_PING_ABILITY, dataParcel, replyParcel, option);
    32. int result = (error == ERR_NONE) ? replyParcel.ReadInt32() : -1;
    33. return result;
    34. }
    1. #include "iremote_object.h"
    2. class TestDeathRecipient : public IRemoteObject::DeathRecipient {
    3. public:
    4. virtual void OnRemoteDied(const wptr& remoteObject);
    5. }
    6. void TestDeathRecipient::OnRemoteDied(const wptr& remoteObject)
    7. {
    8. }
    1. sptr<IPCObjectProxy> object = new IPCObjectProxy(1, to_utf16(DESCRIPTOR));
    2. sptr<IRemoteObject::DeathRecipient> deathRecipient (new TestDeathRecipient());// 构造一个消亡通知对象
    3. bool result = object->AddDeathRecipient(deathRecipient); // 注册消亡通知
    4. 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;}
    
  • 相关阅读:
    Veritas Backup Exec v22.2.1193.1605 数据备份恢复软件
    【测试面试】20K测试工程师会考察哪些能力?
    yolov5量化注意事项
    pycharm pro v2023.2.4(Python开发)
    Java学习 --- 设计模式的适配器模式
    java计算机毕业设计竞赛信息发布及组队系统源码+数据库+lw文档+系统
    【概率论】期中复习笔记(下):大数定律与中心极限定理
    服务器相关
    stable diffusion 零基础入门教程
    angular项目启动报错
  • 原文地址:https://blog.csdn.net/HarmonyOSDev/article/details/133790458