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;}
相关推荐
御承扬3 小时前
Hypium UIViewer 让 MacOS 与鸿蒙NEXT手机实现多屏协同
macos·智能手机·harmonyos·多屏协同
程序猿阿伟13 小时前
《解锁鸿蒙系统AI能力,开启智能应用开发新时代》
人工智能·华为·harmonyos
轻口味13 小时前
【每日学点鸿蒙知识】包体积优化、WebView下载PDF等
华为·pdf·harmonyos
雨汨14 小时前
HarmonyOS 鸿蒙Next 预览pdf文件
华为·pdf·harmonyos
半夜偷删你代码15 小时前
鸿蒙中自定义slider实现字体大小变化
华为·harmonyos·鸿蒙
半夜偷删你代码16 小时前
鸿蒙中调整应用内文字大小
华为·harmonyos
青椒101318 小时前
HarmonyOS(ArkUI框架介绍)
harmonyos
aidou13141 天前
HarmonyOS中实现TabBar(相当于Android中的TabLayout+ViewPager)
华为·harmonyos·tabbar·tabcontent·标签联动
程序猿阿伟1 天前
《探秘鸿蒙NEXT中的人工智能核心架构》
人工智能·架构·harmonyos
轻口味1 天前
HarmonyOS Next 日志工具介绍
华为·pdf·harmonyos