1# Subscribing to State Changes of a Remote Object 2<!--Kit: IPC Kit--> 3<!--Subsystem: Communication--> 4<!--Owner: @xdx19211@luodonghui0157--> 5<!--SE: @zhaopeng_gitee--> 6<!--TSE: @maxiaorong2--> 7 8IPC/RPC allows you to subscribe to the state changes of a remote stub object. When the remote stub object dies, a death notification will be sent to your local proxy. To subscribe to death notifications, you need to call the [registerDeathRecipient](../reference/apis-ipc-kit/js-apis-rpc.md#registerdeathrecipient9-1) API. To unsubscribe from death notifications, call the [unregisterDeathRecipient](../reference/apis-ipc-kit/js-apis-rpc.md#unregisterdeathrecipient9-1) API. 9 10To be specific, you need to inherit the death notification class [DeathRecipient](../reference/apis-ipc-kit/js-apis-rpc.md#deathrecipient) and implement the [onRemoteDied](../reference/apis-ipc-kit/js-apis-rpc.md#onremotedied) method to clear resources. This callback is invoked when the process accommodating the remote stub object exits or the DSoftBus connection on which RPC depends is disabled. 11 12> **NOTE** 13> - The proxy object must first subscribe to death notifications of the stub object. If the stub object is in the normal state, the proxy object can cancel the subscription as required. 14> - If the process of the stub object exits or the DSoftBus connection on which RPC depends is disabled, the [onRemoteDied](../reference/apis-ipc-kit/js-apis-rpc.md#onremotedied) method customized by the proxy object will be automatically triggered. 15 16## When to Use 17 18IPC/RPC subscription is applicable to the following scenarios:<br> 191. In IPC, the proxy object needs to detect the status of the process hosting the remote stub object. 202. In RPC, the proxy object needs to detect the status of the process hosting the remote stub object, or the DSoftBus connection status on which RPC depends. 21When the proxy detects the death of the remote stub object, proxy objects and clear local resources should be cleared. 22> **NOTE** 23> 24> Subscription to death notifications of anonymous stub objects (not registered with SAMgr) is supported in IPC, but not in RPC. 25 26## **Development Using ArkTS APIs** 27 28> **NOTE** 29> 30> - The sample code in this topic implements communication between system applications across processes. 31> 32> - Application scenario constraints: The client is a third-party or system application, and the server is a system application or service. 33 34| API | Return Value Type| Description | 35| ------------------------------------------------------------ | ---------- | ------------------------------------------------------------ | 36| [registerDeathRecipient](../reference/apis-ipc-kit/js-apis-rpc.md#registerdeathrecipient9-1) | void | Registers a callback for receiving death notifications of the remote object. This method should be called on the proxy side.| 37| [unregisterDeathRecipient](../reference/apis-ipc-kit/js-apis-rpc.md#unregisterdeathrecipient9-1) | void | Unregisters from the callback used to receive death notifications of the remote object. | 38| [onRemoteDied](../reference/apis-ipc-kit/js-apis-rpc.md#onremotedied) | void | Called when the process accommodating the remote stub object dies after the proxy successfully registers the death notification.| 39 40### Sample Code 41 42 In IPC, create the variables **want** and **connect**. 43 ```ts 44 import { Want, common } from '@kit.AbilityKit'; 45 import { rpc } from '@kit.IPCKit'; 46 import { hilog } from '@kit.PerformanceAnalysisKit'; 47 48 let proxy: rpc.IRemoteObject | undefined; 49 50 let want: Want = { 51 // Enter the bundle name and ability name. 52 bundleName: "ohos.rpc.test.server", 53 abilityName: "ohos.rpc.test.server.ServiceAbility", 54 }; 55 let connect: common.ConnectOptions = { 56 onConnect: (elementName, remoteProxy) => { 57 hilog.info(0x0000, 'testTag', 'RpcClient: js onConnect called'); 58 proxy = remoteProxy; 59 }, 60 onDisconnect: (elementName) => { 61 hilog.info(0x0000, 'testTag', 'RpcClient: onDisconnect'); 62 }, 63 onFailed: () => { 64 hilog.info(0x0000, 'testTag', 'RpcClient: onFailed'); 65 } 66 }; 67 ``` 68 69 In RPC, create the variables **want** and **connect**. 70 ```ts 71 import { Want, common } from '@kit.AbilityKit'; 72 import { rpc } from '@kit.IPCKit'; 73 import { hilog } from '@kit.PerformanceAnalysisKit'; 74 import { distributedDeviceManager } from '@kit.DistributedServiceKit'; 75 import { BusinessError } from '@kit.BasicServicesKit'; 76 77 let dmInstance: distributedDeviceManager.DeviceManager | undefined; 78 let proxy: rpc.IRemoteObject | undefined; 79 80 try{ 81 dmInstance = distributedDeviceManager.createDeviceManager("ohos.rpc.test"); 82 } catch(error) { 83 let err: BusinessError = error as BusinessError; 84 hilog.error(0x0000, 'testTag', 'createDeviceManager errCode:' + err.code + ', errMessage:' + err.message); 85 } 86 87 // Use distributedDeviceManager to obtain the network ID of the target device. 88 if (dmInstance != undefined) { 89 let deviceList = dmInstance.getAvailableDeviceListSync(); 90 let networkId = deviceList[0].networkId; 91 let want: Want = { 92 bundleName: "ohos.rpc.test.server", 93 abilityName: "ohos.rpc.test.service.ServiceAbility", 94 deviceId: networkId, 95 }; 96 97 let connect: common.ConnectOptions = { 98 onConnect: (elementName, remoteProxy) => { 99 hilog.info(0x0000, 'testTag', 'RpcClient: js onConnect called'); 100 proxy = remoteProxy; 101 }, 102 onDisconnect: (elementName) => { 103 hilog.info(0x0000, 'testTag', 'RpcClient: onDisconnect'); 104 }, 105 onFailed: () => { 106 hilog.info(0x0000, 'testTag', 'RpcClient: onFailed'); 107 } 108 }; 109 } 110 ``` 111 112 In the FA model, the [connectAbility](../reference/apis-ability-kit/js-apis-ability-featureAbility.md#featureabilityconnectability7) API is used to connect to an ability. 113 114 <!--code_no_check_fa--> 115 ```ts 116 import { featureAbility } from '@kit.AbilityKit'; 117 118 // Save the connection ID, which will be used for the subsequent service disconnection. 119 let connectId = featureAbility.connectAbility(want, connect); 120 ``` 121 122 In the stage model, the [connectServiceExtensionAbility](../reference/apis-ability-kit/js-apis-inner-application-uiAbilityContext.md#connectserviceextensionability) API of **common.UIAbilityContext** is used to connect to an ability. 123 In the sample code provided in this topic, **this.context** is used to obtain **UIAbilityContext**, where **this** indicates a UIAbility instance inherited from **UIAbility**. To use **UIAbilityContext** APIs on pages, see [Obtaining the Context of UIAbility](../application-models/uiability-usage.md#obtaining-the-context-of-uiability). 124 125 <!--code_no_check--> 126 ```ts 127 let context: common.UIAbilityContext = this.getUIContext().getHostContext(); // UIAbilityContext 128 // Save the connection ID, which will be used for the subsequent service disconnection. 129 let connectId = context.connectServiceExtensionAbility(want,connect); 130 ``` 131 132 After the service is successfully connected, the proxy object in the **onConnect** callback can be assigned a value You can call the [registerDeathRecipient](../reference/apis-ipc-kit/js-apis-rpc.md#registerdeathrecipient9-1) method of the proxy object to register the death callback. When the proxy object is no longer used, you can call the [unregisterDeathRecipient](../reference/apis-ipc-kit/js-apis-rpc.md#unregisterdeathrecipient9-1) method to deregister the death callback. 133 134 ```ts 135 import { rpc } from '@kit.IPCKit'; 136 import { hilog } from '@kit.PerformanceAnalysisKit'; 137 138 let proxy: rpc.IRemoteObject | undefined; 139 140 class MyDeathRecipient implements rpc.DeathRecipient{ 141 onRemoteDied() { 142 hilog.info(0x0000, 'testTag', 'server died'); 143 } 144 } 145 let deathRecipient = new MyDeathRecipient(); 146 if (proxy != undefined) { 147 // The value 0 is a reserved flag for the death notification of the death listener. It has no actual meaning. 148 proxy.registerDeathRecipient(deathRecipient, 0); 149 proxy.unregisterDeathRecipient(deathRecipient, 0); 150 } 151 ``` 152 153## Reverse Death Notification (Anonymous Stub) 154 155Forward dead notification is a mechanism that allows the proxy to detect death notifications of the stub. To achieve reverse dead notification, you can leverage the forward dead notification mechanism. Suppose there are two processes, A (the process hosting the original stub) and B (the process hosting the original proxy). After obtaining the proxy object of process A, process B creates an anonymous stub object (that is, a stub object not registered with SAMgr), which can be called a callback stub. Then, process B calls [sendMessageRequest](../reference/apis-ipc-kit/js-apis-rpc.md#sendmessagerequest9-2) to send the callback stub to the original stub of process A. Then, process A obtains the callback proxy of process B. As long as the death notification is registered with the callback proxy, when process B (callback stub) dies or the DSoftBus connection on which RPC depends is disabled, the callback proxy can detect the death and notify process A (original stub). In this way, the reverse death notification is implemented. 156 157> **NOTE** 158> - Reverse death notification can only be used for cross-process communication within a device. 159> - When an anonymous stub object is not referenced by any proxy, the object is automatically released. 160