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<IRemoteObject> 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 &data, MessageParcel &reply, MessageOption &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<ITestAbility>**. 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<ITestAbility>**. 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