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

使用场景

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

Native侧接口

接口名

返回值类型

功能描述

AddDeathRecipient(const sptr<DeathRecipient> &recipient);

bool

订阅远端Stub对象状态。

RemoveDeathRecipient(const sptr<DeathRecipient> &recipient);

bool

取消订阅远端Stub对象状态。

OnRemoteDied(const wptr<IRemoteObject> &object);

void

当远端Stub对象死亡时回调。

参考代码

#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侧接口

接口名

返回值类型

功能描述

addDeathRecipient

boolean

注册用于接收远程对象消亡通知的回调,增加proxy对象上的消亡通知。

removeDeathRecipient

boolean

注销用于接收远程对象消亡通知的回调。

onRemoteDied

void

在成功添加死亡通知订阅后,当远端对象死亡时,将自动调用本方法。

参考代码

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指向的时候,内核会自动回收。

参考代码

//Proxy
int 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;
}

  

HarmonyOS远端状态订阅开发实例的更多相关文章

  1. Web Service简介与开发实例

    简介 1.1.Web Service基本概念 Web Service也叫XML Web Service WebService是一种可以接收从Internet或者Intranet上的其它系统中传递过来的 ...

  2. 免费的HTML5连载来了《HTML5网页开发实例详解》连载(二)

    最近新浪.百度.腾讯.京东.大众点评.淘宝等流行的网站都加大了招聘HTML5的力度,HTML5开发人员成了抢手货,本次连载的是由大众点评前端工程师和一淘网前端工程师基情奉献的<HTML5网页开发 ...

  3. 持久化框架Hibernate 开发实例(一)

    1 Hibernate简介 Hibernate框架是一个非常流行的持久化框架,其中在web开发中占据了非常重要的地位, Hibernate作为Web应用的底层,实现了对数据库操作的封装.HIberna ...

  4. 免费的HTML5连载来了《HTML5网页开发实例详解》连载(三)DOCTYPE和字符集

    在2.1.2节中通过新老DOCTYPE的对比,读者可以清晰地看到HTML 5在精简旧有结构上做出的努力.DOCTYPE在出现之初主要用于XML中,用作描述XML允许使用的元素.属性和排列方式.起初HT ...

  5. Shuttle ESB(四)——宣布订阅模式实例介绍(1)

    前,我的重点是关注的三篇文章Shuttle ESB入境和宏观的概念范例. Shuttle ESB模式:请求/对应模式与Pub/Sub模式. 关于这两种模式的区分,请看以下文章的介绍:Shuttle E ...

  6. Thinkphp5整合微信扫码支付开发实例

    ThinkPHP框架是比较多人用的,曾经做过的一个Thinkphp5整合微信扫码支付开发实例,分享出来大家一起学习 打开首页生成订单,并显示支付二维码 public function index() ...

  7. C#软件开发实例.私人订制自己的屏幕截图工具(九)使用自己定义光标,QQ截图时的光标

    版权声明:本文为 testcs_dn(微wx笑) 原创文章,非商用自由转载-保持署名-注明出处,谢谢. https://blog.csdn.net/testcs_dn/article/details/ ...

  8. Java Native Interface 基于JNI的嵌入式手机软件开发实例

    1.通过JNI和c/c++的库组件.其他代码交互 2.java和c不能互通的原因时数据类型问题 Introduction https://docs.oracle.com/javase/8/docs/t ...

  9. 基于Cocos2d-x-1.0.1的飞机大战游戏开发实例(中)

    接<基于Cocos2d-x-1.0.1的飞机大战游戏开发实例(上)> 三.代码分析 1.界面初始化 bool PlaneWarGame::init() { bool bRet = fals ...

  10. Shuttle ESB(四)——公布订阅模式实例介绍(1)

    前面,我已经集中用了三篇文章来讲Shuttle ESB的入门实例与宏观概念. Shuttle ESB一共同拥有两种发送消息的模式:请求/对应模式与Pub/Sub模式. 关于这两种模式的区分.请看以下文 ...

随机推荐

  1. C++ STL容器 set类型

    C++ STL容器 set类型 set是C++引入的二叉树数据结构 特点: 自动将元素排序 插入和删除查找logn 必须元素支持严格的弱顺序 不能改变元素的值 代码 using Group = std ...

  2. Visual Studio部署C++环境下OpenCV库

      本文介绍在Visual Studio 2022中配置.编译C++计算机视觉库OpenCV的方法. 1 OpenCV库配置   首先,我们进行OpenCV库的下载与安装.作为一个开源的库,我们直接在 ...

  3. Mybatis中使用choose/when语句采坑记

    项目中写查询语句的时候,时常会使用到Mybatis中的choose/when语句,根据不同的条件执行不同的分支. 最近在使用这个语句的时候,出现问题导致这个语句不能正确执行,排查很久才解决这个问题,因 ...

  4. SourceTree 摘樱桃 === 遴选 [不要使用这个功能!!不要使用!不要使用!]

    SourceTree 摘樱桃 === 遴选 不要使用摘樱桃!!不要使用!不要使用! 我找了一个文本的git,进行的测试,发现很不好用,文档我又恢复过来了,因为就改了几个字,代码的话,会造成 不可挽回的 ...

  5. c语言中的指针,数组和结构体结合的一个经典案例

    一 你真正懂了C语言了吗? 很多人刚把c语言用了两年,就以为很懂,等遇到稍微深层次一点的问题,就卡住了.这里,有一个问题,可以考察你对这三者理解如何. 二 一个例子: #include <std ...

  6. C++B树的实现

    B树的实现 今天我们就来实现以下B树,B树有什么特点那?我们来列举一下 每个非叶子节点中存放若干关键字数据,并且有若干指向儿子节点的指针.指针数目=关键字数目+1 根节点有最少1个,最多m-1个关键字 ...

  7. HTML(html结构、标签导读 、路径))

    HTML第一天 我们接下来是进行的网页开发网页的相关概念: 什么是网页? 什么是HTML? 网页的形成? 一 什么是网页: 1.网站是指在因特网上根据一定的规则,使用 HTML 等制作的用于展示特定内 ...

  8. Java 实现压缩图片,视频,音频案例

    Java 实现压缩图片,视频,音频案例 在 Java 中,要实现视频压缩通常需要使用外部的库或工具,因为 Java 标准库本身并不提供直接的视频处理功能.以下是一些常用的方法和工具来压缩视频: FFm ...

  9. verilog之预编译

    verilog之预编译 1.基本作用 预编译,就是在verilog进入编译器前的准备工作.一般是完成一些文件的调用,一些编译器的设置,一些参数的定义.一般使用include,define,timesc ...

  10. Django实现发送邮件

    1.获取QQ邮箱授权码 打开QQ邮箱 --> 设置 --> 账号 --> 下拉页面 --> 开启POP3/SMTP服务 --> 短信验证 --> 点击"我 ...