1e41f4b71Sopenharmony_ci# IPC and RPC Development
2e41f4b71Sopenharmony_ci
3e41f4b71Sopenharmony_ci## When to Use
4e41f4b71Sopenharmony_ci
5e41f4b71Sopenharmony_ciIPC/RPC enables a proxy and a stub that run on different processes to communicate with each other, regardless of whether they run on the same or different devices.
6e41f4b71Sopenharmony_ci
7e41f4b71Sopenharmony_ci<!--Del-->
8e41f4b71Sopenharmony_ci## Available APIs
9e41f4b71Sopenharmony_ci
10e41f4b71Sopenharmony_ci**Table 1** Native IPC APIs
11e41f4b71Sopenharmony_ci
12e41f4b71Sopenharmony_ci| API                              | Description                                                            |
13e41f4b71Sopenharmony_ci| ------------------------------------ | ---------------------------------------------------------------- |
14e41f4b71Sopenharmony_ci| sptr&lt;IRemoteObject&gt; AsObject() | Obtains the holder of a remote proxy object. If you call this API on the stub, the **RemoteObject** is returned; if you call this API on the proxy, the proxy object is returned.|
15e41f4b71Sopenharmony_ci| virtual int OnRemoteRequest(uint32_t code, MessageParcel &amp;data, MessageParcel &amp;reply, MessageOption &amp;option) | Called to process a request from the proxy and return the result. Derived classes need to override this API.|
16e41f4b71Sopenharmony_ci| IRemoteProxy | Remote()->SendRequest(code, data, reply, option)  | Sends a request to the peer end. Service proxy classes are derived from the **IRemoteProxy** class.|
17e41f4b71Sopenharmony_ci<!--DelEnd-->
18e41f4b71Sopenharmony_ci
19e41f4b71Sopenharmony_ci## How to Develop
20e41f4b71Sopenharmony_ci
21e41f4b71Sopenharmony_ci<!--Del-->
22e41f4b71Sopenharmony_ci### **Using Native APIs**
23e41f4b71Sopenharmony_ci
24e41f4b71Sopenharmony_ci1. Add dependencies.
25e41f4b71Sopenharmony_ci
26e41f4b71Sopenharmony_ci   SDK dependency:
27e41f4b71Sopenharmony_ci
28e41f4b71Sopenharmony_ci   ```
29e41f4b71Sopenharmony_ci   #IPC scenario
30e41f4b71Sopenharmony_ci   external_deps = [
31e41f4b71Sopenharmony_ci     "ipc:ipc_single",
32e41f4b71Sopenharmony_ci   ]
33e41f4b71Sopenharmony_ci
34e41f4b71Sopenharmony_ci   #RPC scenario
35e41f4b71Sopenharmony_ci   external_deps = [
36e41f4b71Sopenharmony_ci     "ipc:ipc_core",
37e41f4b71Sopenharmony_ci   ]
38e41f4b71Sopenharmony_ci   ```
39e41f4b71Sopenharmony_ci
40e41f4b71Sopenharmony_ci   In addition, the refbase implementation on which IPC/RPC depends is stored in **//utils**. Add the dependency on the Utils source code.
41e41f4b71Sopenharmony_ci
42e41f4b71Sopenharmony_ci   ```
43e41f4b71Sopenharmony_ci   external_deps = [
44e41f4b71Sopenharmony_ci     "c_utils:utils",
45e41f4b71Sopenharmony_ci   ]
46e41f4b71Sopenharmony_ci   ```
47e41f4b71Sopenharmony_ci
48e41f4b71Sopenharmony_ci2. Define the IPC interface **ITestAbility**.
49e41f4b71Sopenharmony_ci
50e41f4b71Sopenharmony_ci   **ITestAbility** inherits the IPC base class **IRemoteBroker** and defines descriptors, functions, and message code. The functions need to be implemented on both the proxy and stub.
51e41f4b71Sopenharmony_ci
52e41f4b71Sopenharmony_ci   ```c++
53e41f4b71Sopenharmony_ci   #include "iremote_broker.h"
54e41f4b71Sopenharmony_ci
55e41f4b71Sopenharmony_ci   // Define message codes.
56e41f4b71Sopenharmony_ci   const int TRANS_ID_PING_ABILITY = 5;
57e41f4b71Sopenharmony_ci
58e41f4b71Sopenharmony_ci   const std::string DESCRIPTOR = "test.ITestAbility";
59e41f4b71Sopenharmony_ci
60e41f4b71Sopenharmony_ci   class ITestAbility : public IRemoteBroker {
61e41f4b71Sopenharmony_ci   public:
62e41f4b71Sopenharmony_ci       // DECLARE_INTERFACE_DESCRIPTOR is mandatory, and the input parameter is std::u16string.
63e41f4b71Sopenharmony_ci       DECLARE_INTERFACE_DESCRIPTOR(to_utf16(DESCRIPTOR));
64e41f4b71Sopenharmony_ci       virtual int TestPingAbility(const std::u16string &dummy) = 0; // Define functions.
65e41f4b71Sopenharmony_ci   };
66e41f4b71Sopenharmony_ci   ```
67e41f4b71Sopenharmony_ci
68e41f4b71Sopenharmony_ci3. Define and implement service provider **TestAbilityStub**.
69e41f4b71Sopenharmony_ci
70e41f4b71Sopenharmony_ci   This class is related to the IPC framework and needs to inherit **IRemoteStub&lt;ITestAbility&gt;**. You need to override **OnRemoteRequest** on the stub to receive requests from the proxy.
71e41f4b71Sopenharmony_ci
72e41f4b71Sopenharmony_ci   ```c++
73e41f4b71Sopenharmony_ci   #include "iability_test.h"
74e41f4b71Sopenharmony_ci   #include "iremote_stub.h"
75e41f4b71Sopenharmony_ci
76e41f4b71Sopenharmony_ci   class TestAbilityStub : public IRemoteStub<ITestAbility> {
77e41f4b71Sopenharmony_ci   public:
78e41f4b71Sopenharmony_ci       virtual int OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override;
79e41f4b71Sopenharmony_ci       int TestPingAbility(const std::u16string &dummy) override;
80e41f4b71Sopenharmony_ci    };
81e41f4b71Sopenharmony_ci
82e41f4b71Sopenharmony_ci   int TestAbilityStub::OnRemoteRequest(uint32_t code,
83e41f4b71Sopenharmony_ci       MessageParcel &data, MessageParcel &reply, MessageOption &option)
84e41f4b71Sopenharmony_ci   {
85e41f4b71Sopenharmony_ci       switch (code) {
86e41f4b71Sopenharmony_ci           case TRANS_ID_PING_ABILITY: {
87e41f4b71Sopenharmony_ci               std::u16string dummy = data.ReadString16();
88e41f4b71Sopenharmony_ci               int result = TestPingAbility(dummy);
89e41f4b71Sopenharmony_ci               reply.WriteInt32(result);
90e41f4b71Sopenharmony_ci               return 0;
91e41f4b71Sopenharmony_ci           }
92e41f4b71Sopenharmony_ci           default:
93e41f4b71Sopenharmony_ci               return IPCObjectStub::OnRemoteRequest(code, data, reply, option);
94e41f4b71Sopenharmony_ci       }
95e41f4b71Sopenharmony_ci   }
96e41f4b71Sopenharmony_ci   ```
97e41f4b71Sopenharmony_ci
98e41f4b71Sopenharmony_ci4. Define the **TestAbility** class that implements functions for the stub.
99e41f4b71Sopenharmony_ci
100e41f4b71Sopenharmony_ci   ```c++
101e41f4b71Sopenharmony_ci   #include "iability_server_test.h"
102e41f4b71Sopenharmony_ci
103e41f4b71Sopenharmony_ci   class TestAbility : public TestAbilityStub {
104e41f4b71Sopenharmony_ci   public:
105e41f4b71Sopenharmony_ci       int TestPingAbility(const std::u16string &dummy);
106e41f4b71Sopenharmony_ci   }
107e41f4b71Sopenharmony_ci
108e41f4b71Sopenharmony_ci   int TestAbility::TestPingAbility(const std::u16string &dummy) {
109e41f4b71Sopenharmony_ci       return 0;
110e41f4b71Sopenharmony_ci   }
111e41f4b71Sopenharmony_ci   ```
112e41f4b71Sopenharmony_ci
113e41f4b71Sopenharmony_ci5. Define and implement **TestAbilityProxy**.
114e41f4b71Sopenharmony_ci
115e41f4b71Sopenharmony_ci   This class is implemented on the proxy and inherits **IRemoteProxy&lt;ITestAbility&gt;**. You can call **SendRequest** to send a request to the stub and expose the capabilities provided by the stub.
116e41f4b71Sopenharmony_ci
117e41f4b71Sopenharmony_ci   ```c++
118e41f4b71Sopenharmony_ci   #include "iability_test.h"
119e41f4b71Sopenharmony_ci   #include "iremote_proxy.h"
120e41f4b71Sopenharmony_ci   #include "iremote_object.h"
121e41f4b71Sopenharmony_ci
122e41f4b71Sopenharmony_ci   class TestAbilityProxy : public IRemoteProxy<ITestAbility> {
123e41f4b71Sopenharmony_ci   public:
124e41f4b71Sopenharmony_ci       explicit TestAbilityProxy(const sptr<IRemoteObject> &impl);
125e41f4b71Sopenharmony_ci       int TestPingAbility(const std::u16string &dummy) override;
126e41f4b71Sopenharmony_ci   private:
127e41f4b71Sopenharmony_ci       static inline BrokerDelegator<TestAbilityProxy> delegator_; // For use of the iface_cast macro at a later time
128e41f4b71Sopenharmony_ci   }
129e41f4b71Sopenharmony_ci
130e41f4b71Sopenharmony_ci   TestAbilityProxy::TestAbilityProxy(const sptr<IRemoteObject> &impl)
131e41f4b71Sopenharmony_ci       : IRemoteProxy<ITestAbility>(impl)
132e41f4b71Sopenharmony_ci   {
133e41f4b71Sopenharmony_ci   }
134e41f4b71Sopenharmony_ci
135e41f4b71Sopenharmony_ci   int TestAbilityProxy::TestPingAbility(const std::u16string &dummy){
136e41f4b71Sopenharmony_ci       MessageOption option;
137e41f4b71Sopenharmony_ci       MessageParcel dataParcel, replyParcel;
138e41f4b71Sopenharmony_ci       dataParcel.WriteString16(dummy);
139e41f4b71Sopenharmony_ci       int error = Remote()->SendRequest(TRANS_ID_PING_ABILITY, dataParcel, replyParcel, option);
140e41f4b71Sopenharmony_ci       int result = (error == ERR_NONE) ? replyParcel.ReadInt32() : -1;
141e41f4b71Sopenharmony_ci       return result;
142e41f4b71Sopenharmony_ci   }
143e41f4b71Sopenharmony_ci   ```
144e41f4b71Sopenharmony_ci
145e41f4b71Sopenharmony_ci6. Register and start an SA.
146e41f4b71Sopenharmony_ci
147e41f4b71Sopenharmony_ci   Call **AddSystemAbility** to register the **TestAbilityStub** instance of the SA with **SystemAbilityManager**. The registration parameters vary depending on whether the **SystemAbilityManager** resides on the same device as the SA.
148e41f4b71Sopenharmony_ci
149e41f4b71Sopenharmony_ci   ```c++
150e41f4b71Sopenharmony_ci   // Register the TestAbilityStub instance with the SystemAbilityManager on the same device as the SA.
151e41f4b71Sopenharmony_ci   auto samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
152e41f4b71Sopenharmony_ci   samgr->AddSystemAbility(saId, new TestAbility());
153e41f4b71Sopenharmony_ci
154e41f4b71Sopenharmony_ci   // Register the TestAbilityStub instance with the SystemAbilityManager on a different device.
155e41f4b71Sopenharmony_ci   auto samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
156e41f4b71Sopenharmony_ci   ISystemAbilityManager::SAExtraProp saExtra;
157e41f4b71Sopenharmony_ci   saExtra.isDistributed = true; // Set a distributed SA.
158e41f4b71Sopenharmony_ci   int result = samgr->AddSystemAbility(saId, new TestAbility(), saExtra);
159e41f4b71Sopenharmony_ci   ```
160e41f4b71Sopenharmony_ci
161e41f4b71Sopenharmony_ci7. Obtain the SA.
162e41f4b71Sopenharmony_ci
163e41f4b71Sopenharmony_ci   Call the **GetSystemAbility** function of the **SystemAbilityManager** class to obtain the **IRemoteObject** for the SA, and create a **TestAbilityProxy** instance.
164e41f4b71Sopenharmony_ci
165e41f4b71Sopenharmony_ci   ```c++
166e41f4b71Sopenharmony_ci   // Obtain the proxy of the SA registered on the local device.
167e41f4b71Sopenharmony_ci   sptr<ISystemAbilityManager> samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
168e41f4b71Sopenharmony_ci   sptr<IRemoteObject> remoteObject = samgr->GetSystemAbility(saId);
169e41f4b71Sopenharmony_ci   sptr<ITestAbility> testAbility = iface_cast<ITestAbility>(remoteObject); // Use the iface_cast macro to convert the proxy to a specific type.
170e41f4b71Sopenharmony_ci
171e41f4b71Sopenharmony_ci   // Obtain the proxy of the SA registered with any other devices.
172e41f4b71Sopenharmony_ci   sptr<ISystemAbilityManager> samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
173e41f4b71Sopenharmony_ci
174e41f4b71Sopenharmony_ci   // networkId is the device identifier and can be obtained through GetLocalNodeDeviceInfo.
175e41f4b71Sopenharmony_ci   sptr<IRemoteObject> remoteObject = samgr->GetSystemAbility(saId, networkId);
176e41f4b71Sopenharmony_ci   sptr<TestAbilityProxy> proxy(new TestAbilityProxy(remoteObject)); // Construct a proxy.
177e41f4b71Sopenharmony_ci   ```
178e41f4b71Sopenharmony_ci<!--DelEnd-->
179e41f4b71Sopenharmony_ci### **Using ArkTS APIs**
180e41f4b71Sopenharmony_ci
181e41f4b71Sopenharmony_ci> **NOTE**
182e41f4b71Sopenharmony_ci>
183e41f4b71Sopenharmony_ci> - The sample code in this topic implements communication between system applications across processes.
184e41f4b71Sopenharmony_ci>
185e41f4b71Sopenharmony_ci> - Currently, third-party applications cannot implement ServiceExtensionAbility. The UIAbility components of a third-party application can connect to the ServiceExtensionAbility provided by the system via **Context**.
186e41f4b71Sopenharmony_ci>
187e41f4b71Sopenharmony_ci> - The development applies only to the scenario, in which the client is a third-party application and the server is a system application.
188e41f4b71Sopenharmony_ci
189e41f4b71Sopenharmony_ci1. Add dependencies.
190e41f4b71Sopenharmony_ci
191e41f4b71Sopenharmony_ci   ```ts
192e41f4b71Sopenharmony_ci    // If the FA model is used, import featureAbility from @kit.AbilityKit.
193e41f4b71Sopenharmony_ci    // import { featureAbility } from '@kit.AbilityKit';
194e41f4b71Sopenharmony_ci    import { rpc } from '@kit.IPCKit';
195e41f4b71Sopenharmony_ci   ```
196e41f4b71Sopenharmony_ci
197e41f4b71Sopenharmony_ci2. Connect to the desired ability.
198e41f4b71Sopenharmony_ci
199e41f4b71Sopenharmony_ci   Construct the **want** variable, and specify the bundle name and component name of the application where the ability is located. If cross-device communication is involved, also specify the network ID of the target device, which can be obtained through **distributedDeviceManager**. Then, construct the **connect** variable, and specify the callbacks to be invoked when the ability is connected, disconnect, and the connection fails. If you use the FA model, call the API provided by **featureAbility** to connect to an ability. If you use the stage model, obtain a service instance through **Context**, and then call the API provided by **featureAbility** to connect to an ability.
200e41f4b71Sopenharmony_ci
201e41f4b71Sopenharmony_ci   ```ts
202e41f4b71Sopenharmony_ci    // If the FA model is used, import featureAbility from @kit.AbilityKit.
203e41f4b71Sopenharmony_ci    // import { featureAbility } from "@kit.AbilityKit";
204e41f4b71Sopenharmony_ci    import { Want, common } from '@kit.AbilityKit';
205e41f4b71Sopenharmony_ci    import { rpc } from '@kit.IPCKit';
206e41f4b71Sopenharmony_ci    import { hilog } from '@kit.PerformanceAnalysisKit';
207e41f4b71Sopenharmony_ci    import { distributedDeviceManager } from '@kit.DistributedServiceKit';
208e41f4b71Sopenharmony_ci    import { BusinessError } from '@kit.BasicServicesKit';
209e41f4b71Sopenharmony_ci
210e41f4b71Sopenharmony_ci    let dmInstance: distributedDeviceManager.DeviceManager | undefined;
211e41f4b71Sopenharmony_ci    let proxy: rpc.IRemoteObject | undefined;
212e41f4b71Sopenharmony_ci    let connectId: number;
213e41f4b71Sopenharmony_ci
214e41f4b71Sopenharmony_ci    // Connect to an ability on a single device.
215e41f4b71Sopenharmony_ci    let want: Want = {
216e41f4b71Sopenharmony_ci      // Enter the bundle name and ability name.
217e41f4b71Sopenharmony_ci      bundleName: "ohos.rpc.test.server",
218e41f4b71Sopenharmony_ci      abilityName: "ohos.rpc.test.server.ServiceAbility",
219e41f4b71Sopenharmony_ci    };
220e41f4b71Sopenharmony_ci    let connect: common.ConnectOptions = {
221e41f4b71Sopenharmony_ci      onConnect: (elementName, remoteProxy) => {
222e41f4b71Sopenharmony_ci        hilog.info(0x0000, 'testTag', 'RpcClient: js onConnect called');
223e41f4b71Sopenharmony_ci        proxy = remoteProxy;
224e41f4b71Sopenharmony_ci      },
225e41f4b71Sopenharmony_ci      onDisconnect: (elementName) => {
226e41f4b71Sopenharmony_ci        hilog.info(0x0000, 'testTag', 'RpcClient: onDisconnect');
227e41f4b71Sopenharmony_ci      },
228e41f4b71Sopenharmony_ci      onFailed: () => {
229e41f4b71Sopenharmony_ci        hilog.info(0x0000, 'testTag', 'RpcClient: onFailed');
230e41f4b71Sopenharmony_ci      }
231e41f4b71Sopenharmony_ci    };
232e41f4b71Sopenharmony_ci    // Use this method to connect to the ability in the FA model.
233e41f4b71Sopenharmony_ci    // connectId = featureAbility.connectAbility(want, connect);
234e41f4b71Sopenharmony_ci
235e41f4b71Sopenharmony_ci    let context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext; // UIAbilityContext
236e41f4b71Sopenharmony_ci    // Save the connection ID, which will be used when the ability is disconnected.
237e41f4b71Sopenharmony_ci    connectId = context.connectServiceExtensionAbility(want,connect);
238e41f4b71Sopenharmony_ci
239e41f4b71Sopenharmony_ci    // Connect to an ability across devices.
240e41f4b71Sopenharmony_ci    try{
241e41f4b71Sopenharmony_ci      dmInstance = distributedDeviceManager.createDeviceManager("ohos.rpc.test");
242e41f4b71Sopenharmony_ci    } catch(error) {
243e41f4b71Sopenharmony_ci      let err: BusinessError = error as BusinessError;
244e41f4b71Sopenharmony_ci      hilog.error(0x0000, 'testTag', 'createDeviceManager errCode:' + err.code + ', errMessage:' + err.message);
245e41f4b71Sopenharmony_ci    }
246e41f4b71Sopenharmony_ci
247e41f4b71Sopenharmony_ci    // Use distributedDeviceManager to obtain the network ID of the target device.
248e41f4b71Sopenharmony_ci    if (dmInstance != undefined) {
249e41f4b71Sopenharmony_ci      let deviceList = dmInstance.getAvailableDeviceListSync();
250e41f4b71Sopenharmony_ci      let networkId = deviceList[0].networkId;
251e41f4b71Sopenharmony_ci      let want: Want = {
252e41f4b71Sopenharmony_ci        bundleName: "ohos.rpc.test.server",
253e41f4b71Sopenharmony_ci        abilityName: "ohos.rpc.test.service.ServiceAbility",
254e41f4b71Sopenharmony_ci        deviceId: networkId,
255e41f4b71Sopenharmony_ci        flags: 256
256e41f4b71Sopenharmony_ci      };
257e41f4b71Sopenharmony_ci      // Save the connection ID, which will be used when the ability is disconnected.
258e41f4b71Sopenharmony_ci      // Use this method to connect to the ability in the FA model.
259e41f4b71Sopenharmony_ci      // connectId = featureAbility.connectAbility(want, connect);
260e41f4b71Sopenharmony_ci
261e41f4b71Sopenharmony_ci      // The first parameter specifies the bundle name of the application, and the second parameter specifies the callback used to return the network ID obtained by using distributedDeviceManager.
262e41f4b71Sopenharmony_ci      connectId = context.connectServiceExtensionAbility(want,connect);
263e41f4b71Sopenharmony_ci    }
264e41f4b71Sopenharmony_ci   ```
265e41f4b71Sopenharmony_ci
266e41f4b71Sopenharmony_ci3. Process requests sent from the client.
267e41f4b71Sopenharmony_ci
268e41f4b71Sopenharmony_ci   Call **onConnect()** to return a proxy object inherited from [rpc.RemoteObject](../reference/apis-ipc-kit/js-apis-rpc.md#remoteobject) after the ability is successfully connected. Implement [onRemoteMessageRequest](../reference/apis-ipc-kit/js-apis-rpc.md#onremotemessagerequest9) for the proxy object to process requests sent from the client.
269e41f4b71Sopenharmony_ci
270e41f4b71Sopenharmony_ci   ```ts
271e41f4b71Sopenharmony_ci    import { rpc } from '@kit.IPCKit';
272e41f4b71Sopenharmony_ci    import { Want } from '@kit.AbilityKit';
273e41f4b71Sopenharmony_ci    class Stub extends rpc.RemoteObject {
274e41f4b71Sopenharmony_ci      constructor(descriptor: string) {
275e41f4b71Sopenharmony_ci        super(descriptor);
276e41f4b71Sopenharmony_ci      }
277e41f4b71Sopenharmony_ci      onRemoteMessageRequest(code: number, data: rpc.MessageSequence, reply: rpc.MessageSequence, option: rpc.MessageOption): boolean | Promise<boolean> {
278e41f4b71Sopenharmony_ci        // Process requests sent from the client based on the code.
279e41f4b71Sopenharmony_ci        return true;
280e41f4b71Sopenharmony_ci      }
281e41f4b71Sopenharmony_ci
282e41f4b71Sopenharmony_ci      onConnect(want: Want) {
283e41f4b71Sopenharmony_ci        const robj: rpc.RemoteObject = new Stub("rpcTestAbility");
284e41f4b71Sopenharmony_ci        return robj;
285e41f4b71Sopenharmony_ci      }
286e41f4b71Sopenharmony_ci    }
287e41f4b71Sopenharmony_ci   ```
288e41f4b71Sopenharmony_ci
289e41f4b71Sopenharmony_ci4. Process responses sent from the server.
290e41f4b71Sopenharmony_ci
291e41f4b71Sopenharmony_ci   Receive the proxy object in the **onConnect** callback, call [sendMessageRequest](../reference/apis-ipc-kit/js-apis-rpc.md#sendmessagerequest9-2) to send a request, and receive the response using a callback or a promise (an object representing the eventual completion or failure of an asynchronous operation and its result value).
292e41f4b71Sopenharmony_ci
293e41f4b71Sopenharmony_ci   ```ts
294e41f4b71Sopenharmony_ci    import { rpc } from '@kit.IPCKit';
295e41f4b71Sopenharmony_ci    import { hilog } from '@kit.PerformanceAnalysisKit';
296e41f4b71Sopenharmony_ci
297e41f4b71Sopenharmony_ci    // Use a promise.
298e41f4b71Sopenharmony_ci    let option = new rpc.MessageOption();
299e41f4b71Sopenharmony_ci    let data = rpc.MessageSequence.create();
300e41f4b71Sopenharmony_ci    let reply = rpc.MessageSequence.create();
301e41f4b71Sopenharmony_ci    // Write parameters to data.
302e41f4b71Sopenharmony_ci    let proxy: rpc.IRemoteObject | undefined;
303e41f4b71Sopenharmony_ci    if (proxy != undefined) {
304e41f4b71Sopenharmony_ci      proxy.sendMessageRequest(1, data, reply, option)
305e41f4b71Sopenharmony_ci        .then((result: rpc.RequestResult) => {
306e41f4b71Sopenharmony_ci          if (result.errCode != 0) {
307e41f4b71Sopenharmony_ci            hilog.error(0x0000, 'testTag', 'sendMessageRequest failed, errCode: ' + result.errCode);
308e41f4b71Sopenharmony_ci            return;
309e41f4b71Sopenharmony_ci          }
310e41f4b71Sopenharmony_ci          // Read the result from result.reply.
311e41f4b71Sopenharmony_ci        })
312e41f4b71Sopenharmony_ci        .catch((e: Error) => {
313e41f4b71Sopenharmony_ci          hilog.error(0x0000, 'testTag', 'sendMessageRequest got exception: ' + e);
314e41f4b71Sopenharmony_ci        })
315e41f4b71Sopenharmony_ci        .finally(() => {
316e41f4b71Sopenharmony_ci          data.reclaim();
317e41f4b71Sopenharmony_ci          reply.reclaim();
318e41f4b71Sopenharmony_ci        })
319e41f4b71Sopenharmony_ci    }
320e41f4b71Sopenharmony_ci
321e41f4b71Sopenharmony_ci    // Use a callback.
322e41f4b71Sopenharmony_ci    function sendRequestCallback(err: Error, result: rpc.RequestResult) {
323e41f4b71Sopenharmony_ci      try {
324e41f4b71Sopenharmony_ci        if (result.errCode != 0) {
325e41f4b71Sopenharmony_ci          hilog.error(0x0000, 'testTag', 'sendMessageRequest failed, errCode: ' + result.errCode);
326e41f4b71Sopenharmony_ci          return;
327e41f4b71Sopenharmony_ci        }
328e41f4b71Sopenharmony_ci        // Read the result from result.reply.
329e41f4b71Sopenharmony_ci      } finally {
330e41f4b71Sopenharmony_ci          result.data.reclaim();
331e41f4b71Sopenharmony_ci          result.reply.reclaim();
332e41f4b71Sopenharmony_ci      }
333e41f4b71Sopenharmony_ci    }
334e41f4b71Sopenharmony_ci    let options = new rpc.MessageOption();
335e41f4b71Sopenharmony_ci    let datas = rpc.MessageSequence.create();
336e41f4b71Sopenharmony_ci    let replys = rpc.MessageSequence.create();
337e41f4b71Sopenharmony_ci    // Write parameters to data.
338e41f4b71Sopenharmony_ci    if (proxy != undefined) {
339e41f4b71Sopenharmony_ci      proxy.sendMessageRequest(1, datas, replys, options, sendRequestCallback);
340e41f4b71Sopenharmony_ci    }
341e41f4b71Sopenharmony_ci   ```
342e41f4b71Sopenharmony_ci
343e41f4b71Sopenharmony_ci5. Tear down the connection.
344e41f4b71Sopenharmony_ci
345e41f4b71Sopenharmony_ci   If you use the FA model, call the API provided by **featureAbility** to tear down the connection when the communication is over. If you use the stage model, obtain a service instance through **Context**, and then call the API provided by **featureAbility** to tear down the connection.
346e41f4b71Sopenharmony_ci
347e41f4b71Sopenharmony_ci   ```ts
348e41f4b71Sopenharmony_ci    // If the FA model is used, import featureAbility from @kit.AbilityKit.
349e41f4b71Sopenharmony_ci    // import { featureAbility } from "@kit.AbilityKit";
350e41f4b71Sopenharmony_ci    import { Want, common } from '@kit.AbilityKit';
351e41f4b71Sopenharmony_ci    import { rpc } from '@kit.IPCKit';
352e41f4b71Sopenharmony_ci    import { hilog } from '@kit.PerformanceAnalysisKit';
353e41f4b71Sopenharmony_ci
354e41f4b71Sopenharmony_ci    function disconnectCallback() {
355e41f4b71Sopenharmony_ci      hilog.info(0x0000, 'testTag', 'disconnect ability done');
356e41f4b71Sopenharmony_ci    }
357e41f4b71Sopenharmony_ci    // Use this method to disconnect from the ability in the FA model.
358e41f4b71Sopenharmony_ci    // featureAbility.disconnectAbility(connectId, disconnectCallback);
359e41f4b71Sopenharmony_ci
360e41f4b71Sopenharmony_ci    let proxy: rpc.IRemoteObject | undefined;
361e41f4b71Sopenharmony_ci    let connectId: number;
362e41f4b71Sopenharmony_ci
363e41f4b71Sopenharmony_ci    // Connect to an ability on a single device.
364e41f4b71Sopenharmony_ci    let want: Want = {
365e41f4b71Sopenharmony_ci      // Enter the bundle name and ability name.
366e41f4b71Sopenharmony_ci      bundleName: "ohos.rpc.test.server",
367e41f4b71Sopenharmony_ci      abilityName: "ohos.rpc.test.server.ServiceAbility",
368e41f4b71Sopenharmony_ci    };
369e41f4b71Sopenharmony_ci    let connect: common.ConnectOptions = {
370e41f4b71Sopenharmony_ci      onConnect: (elementName, remote) => {
371e41f4b71Sopenharmony_ci        proxy = remote;
372e41f4b71Sopenharmony_ci      },
373e41f4b71Sopenharmony_ci      onDisconnect: (elementName) => {
374e41f4b71Sopenharmony_ci      },
375e41f4b71Sopenharmony_ci      onFailed: () => {
376e41f4b71Sopenharmony_ci        proxy;
377e41f4b71Sopenharmony_ci      }
378e41f4b71Sopenharmony_ci    };
379e41f4b71Sopenharmony_ci    // Use this method to connect to the ability in the FA model.
380e41f4b71Sopenharmony_ci    // connectId = featureAbility.connectAbility(want, connect);
381e41f4b71Sopenharmony_ci
382e41f4b71Sopenharmony_ci    connectId = this.context.connectServiceExtensionAbility(want,connect);
383e41f4b71Sopenharmony_ci
384e41f4b71Sopenharmony_ci    this.context.disconnectServiceExtensionAbility(connectId);
385e41f4b71Sopenharmony_ci   ```
386e41f4b71Sopenharmony_ci
387