ipc-rpc-development-guideline.md 5.3 KB
Newer Older
Z
zengyawen 已提交
1
# IPC与RPC通信开发指导
M
mamingshuai 已提交
2

Z
zengyawen 已提交
3
## 场景介绍
M
mamingshuai 已提交
4 5 6 7

IPC/RPC的主要工作是让运行在不同进程的Proxy和Stub互相通信,包括Proxy和Stub运行在不同设备的情况。


Z
zengyawen 已提交
8
## 接口说明
M
mamingshuai 已提交
9

Z
zengyawen 已提交
10
**表1** Native侧IPC接口
M
mamingshuai 已提交
11

Z
zengyawen 已提交
12 13
| 类/接口 | 方法 | 功能说明 | 
| -------- | -------- | -------- |
14
| [IRemoteBroker](../reference/apis/js-apis-rpc.md#iremotebroker) | sptr<IRemoteObject> AsObject() | 返回通信对象。派生类需要实现,Stub端返回RemoteObject对象本身,Proxy端返回代理对象。 | 
15 16
| IRemoteStub | virtual int OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) | 请求处理方法,派生类需要重写该方法用来处理Proxy的请求并返回结果。 | 
| IRemoteProxy |  | 业务Proxy类,派生自IRemoteProxy类。 | 
M
mamingshuai 已提交
17 18


Z
zengyawen 已提交
19
## 开发步骤
M
mamingshuai 已提交
20

Z
zengyawen 已提交
21
**Native侧开发步骤**
M
mamingshuai 已提交
22

Z
zengyawen 已提交
23
1. 定义IPC接口ITestAbility
24

Z
zengyawen 已提交
25 26 27 28 29
   SA接口继承IPC基类接口IRemoteBroker,接口里定义描述符、业务函数和消息码,其中业务函数在Proxy端和Stub端都需要实现。

   ```
   class ITestAbility : public IRemoteBroker {
   public:
30 31 32 33
       // DECLARE_INTERFACE_DESCRIPTOR是必需的,入参需使用std::u16string;
       DECLARE_INTERFACE_DESCRIPTOR("test.ITestAbility");
       int TRANS_ID_PING_ABILITY = 1; // 定义消息码
       virtual int TestPingAbility(const std::u16string &dummy) = 0; // 定义业务函数
Z
zengyawen 已提交
34 35 36 37
   };
   ```

2. 定义和实现服务端TestAbilityStub
38

Z
zengyawen 已提交
39 40 41 42 43 44 45
   该类是和IPC框架相关的实现,需要继承 IRemoteStub<ITestAbility>。Stub端作为接收请求的一端,需重写OnRemoteRequest方法用于接收客户端调用。

   ```
   class TestAbilityStub : public IRemoteStub<ITestAbility> {
   public:    
       virtual int OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override;
       int TestPingAbility(const std::u16string &dummy) override;
M
mamingshuai 已提交
46
    };
Z
zengyawen 已提交
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
   
   int TestServiceStub::OnRemoteRequest(uint32_t code,
       MessageParcel &data, MessageParcel &reply, MessageOption &option)
   {
       switch (code) {
           case TRANS_ID_PING_ABILITY: {
               std::u16string dummy = data.ReadString16();
               int result = TestPingAbility(dummy);
               reply.WriteInt32(result);
               return 0;
           }
           default:
               return IPCObjectStub::OnRemoteRequest(code, data, reply, option);
       }
   }
   ```

3. 定义服务端业务函数具体实现类TestAbility
   ```
   class TestAbility : public TestAbilityStub {
   public:
       int TestPingAbility(const std::u16string &dummy);
   }
   
   int TestAbility::TestPingAbility(const std::u16string &dummy) {
       return 0;
   }
   ```

4. 定义和实现客户端 TestAbilityProxy
77

Z
zengyawen 已提交
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
   该类是Proxy端实现,继承IRemoteProxy&lt;ITestAbility&gt;,调用SendRequest接口向Stub端发送请求,对外暴露服务端提供的能力。

   ```
   class TestAbilityProxy : public IRemoteProxy<ITestAbility> {
   public:
       explicit TestAbilityProxy(const sptr<IRemoteObject> &impl);
       int TestPingService(const std::u16string &dummy) override;
   private:
       static inline BrokerDelegator<TestAbilityProxy> delegator_; // 方便后续使用iface_cast宏
   }
   
   TestAbilityProxy::TestAbilityProxy(const sptr<IRemoteObject> &impl)
       : IRemoteProxy<ITestAbility>(impl)
   {
   }
   
   int TestAbilityProxy::TestPingService(const std::u16string &dummy){
       MessageOption option;
       MessageParcel dataParcel, replyParcel;
       dataParcel.WriteString16(dummy);
       int error = Remote()->SendRequest(TRANS_ID_PING_ABILITY, dataParcel, replyParcel, option);
       int result = (error == ERR_NONE) ? replyParcel.ReadInt32() : -1;
       return result;
M
mamingshuai 已提交
101
    }
Z
zengyawen 已提交
102 103
   ```

104 105 106
5. SA注册与启动

   SA需要将自己的TestAbilityStub实例通过AddSystemAbility接口注册到SystemAbilityManager,设备内与分布式的注册参数不同。
Z
zengyawen 已提交
107 108 109 110

   ```
   // 注册到本设备内
   auto samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
E
Eight_J 已提交
111
   samgr->AddSystemAbility(saId, new TestAbility());
Z
zengyawen 已提交
112 113 114 115 116
   
   // 在组网场景下,会被同步到其他设备上
   auto samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
   ISystemAbilityManager::SAExtraProp saExtra;
   saExtra.isDistributed = true; // 设置为分布式SA
E
Eight_J 已提交
117
   int result = samgr->AddSystemAbility(saId, new TestAbility(), saExtra);
Z
zengyawen 已提交
118 119
   ```

120 121
6. SA获取与调用

Z
zengyawen 已提交
122 123 124 125 126
   通过SystemAbilityManager的GetSystemAbility方法可获取到对应SA的代理IRemoteObject,然后构造TestAbilityProxy即可。

   ```
   // 获取本设备内注册的SA的proxy
   sptr<ISystemAbilityManager> samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
E
Eight_J 已提交
127
   sptr<IRemoteObject> remoteObject = samgr->GetSystemAbility(saId);
Z
zengyawen 已提交
128 129
   sptr<ITestAbility> testAbility = iface_cast<ITestAbility>(remoteObject); // 使用iface_cast宏转换成具体类型
   
130
   // 获取其他设备注册的SA的proxy
Z
zengyawen 已提交
131
   sptr<ISystemAbilityManager> samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
E
Eight_J 已提交
132
   sptr<IRemoteObject> remoteObject = samgr->GetSystemAbility(saId, deviceId); // deviceId是指定设备的标识符
Z
zengyawen 已提交
133 134
   sptr<TestAbilityProxy> proxy(new TestAbilityProxy(remoteObject)); // 直接构造具体Proxy
   ```
Z
zengyawen 已提交
135