1# Application Recovery Development 2 3## When to Use 4 5During application running, some unexpected behaviors are inevitable. For example, unprocessed exceptions and errors are thrown, and the call or running constraints of the framework are violated. 6 7By default, the processes will exit as exception handling. However, if user data is generated during application use, process exits may interrupt user operations and cause data loss. 8In this way, application recovery APIs may help you save temporary data, restart an application after it exits, and restore its status and data, which deliver a better user experience. 9 10Currently, the APIs support only the development of an application that adopts the stage model, single process, and single ability. 11 12## Available APIs 13 14The application recovery APIs are provided by the **appRecovery** module, which can be imported via **import**. For details, please refer to [Development Example](#development-example). This document describes behaviors of APIs in API version 9, and the content will update with changes. 15 16### Available APIs 17 18| API | Description | 19| ------------------------------------------------------------ | ---------------------------------------------------- | 20| enableAppRecovery(restart?: RestartFlag, saveOccasion?: SaveOccasionFlag, saveMode?: SaveModeFlag) : void; | Enables the application recovery function.| 21| saveAppState(): boolean; | Saves the ability status of an application. | 22| restartApp(): void; | Restarts the current process. If there is saved ability status, it will be passed to the **want** parameter's **wantParam** attribute of the **onCreate** lifecycle callback of the ability.| 23 24The APIs are used for troubleshooting and do not return any exception. Therefore, you need to be familiar with when they are used. 25 26**enableAppRecovery**: This API should be called during application initialization. For example, you can call this API in **onCreate** of **AbilityStage**. For details, please refer to the [parameter description](../reference/apis/js-apis-app-ability-appRecovery.md). 27 28**saveAppState**: After this API is called, the framework calls back **onSaveState** of the ability. If data saving is agreed to in this method, relevant data and the page stack of the ability are persisted to the local cache of the application. 29 30**restartApp**: After this API is called, the framework kills the current application process and restarts the ability in the foreground, with **APP_RECOVERY** specified as the startup cause. 31 32### Framework Fault Management Process 33 34Fault management is an important way for applications to deliver a better user experience. The application framework offers three methods for application fault management: fault listening, fault rectification, and fault query. 35 36- Fault listening refers to the process of registering [ErrorObserver](../reference/apis/js-apis-inner-application-errorObserver.md) via [errorManager](../reference/apis/js-apis-app-ability-errorManager.md), listening for fault occurrence, and notifying the fault listener. 37 38- Fault rectification refers to [appRecovery](../reference/apis/js-apis-app-ability-appRecovery.md) and restarts an application to restore its status previous to a fault. 39 40- Fault query indicates that [faultLogger](../reference/apis/js-apis-faultLogger.md) obtains the fault information using its query API. 41 42The figure below does not illustrate the time when [faultLogger](../reference/apis/js-apis-faultLogger.md) is called. You can refer to [LastExitReason](../reference/apis/js-apis-app-ability-abilityConstant.md#abilityconstantlastexitreason) passed during application initialization to determine whether to call [faultLogger](../reference/apis/js-apis-faultLogger.md) to query the information about the last fault. 43 44It is recommended that you call [errorManager](../reference/apis/js-apis-app-ability-errorManager.md) to process the exception. After the processing is complete, you can call the status saving API and restart the application. 45If you do not register [ErrorObserver](../reference/apis/js-apis-inner-application-errorObserver.md) or enable application recovery, the application process will exit according to the default processing logic of the system. Users can restart the application from the home screen. 46If you have enabled application recovery, the framework first checks whether a fault allows for ability status saving and whether you have configured ability status saving. If so, [onSaveState](../reference/apis/js-apis-app-ability-uiAbility.md#uiabilityonsavestate) of [Ability](../reference/apis/js-apis-app-ability-uiAbility.md) is called back. Finally, the application is restarted. 47 48### Scenarios Supported by Application Fault Management APIs 49 50Common fault types include JavaScript application crash, application freezing, and C++ application crash. Generally, an application is closed when a crash occurs. Application freezing occurs when the application does not respond. The fault type can be ignored for the upper layer of an application. The recovery framework implements fault management in different scenarios based on the fault type. 51 52| Fault | Fault Listening | Status Saving| Automatic Restart| Log Query| 53| ----------|--------- |--------- |--------- |--------- | 54| [JS_CRASH](../reference/apis/js-apis-faultLogger.md#faulttype) | Supported|Supported|Supported|Supported| 55| [APP_FREEZE](../reference/apis/js-apis-faultLogger.md#faulttype) | Not supported|Not supported|Supported|Supported| 56| [CPP_CRASH](../reference/apis/js-apis-faultLogger.md#faulttype) | Not supported|Not supported|Not supported|Supported| 57 58**Status Saving** in the table header means status saving when a fault occurs. To protect user data as much as possible in the application freezing fault, you can adopt either the periodic or automatic way, and the latter will save user data when an ability is switched to the background. 59 60 61 62## Development Example 63 64### Enabling Application Recovery 65 66 Enable **appRecovery** during application initialization. The following is an example of **AbilityStage**: 67 68```ts 69import AbilityStage from '@ohos.app.ability.AbilityStage' 70import appRecovery from '@ohos.app.ability.appRecovery' 71 72export default class MyAbilityStage extends AbilityStage { 73 onCreate() { 74 console.info("[Demo] MyAbilityStage onCreate") 75 appRecovery.enableAppRecovery(appRecovery.RestartFlag.ALWAYS_RESTART, 76 appRecovery.SaveOccasionFlag.SAVE_WHEN_ERROR | appRecovery.SaveOccasionFlag.SAVE_WHEN_BACKGROUND, 77 appRecovery.SaveModeFlag.SAVE_WITH_FILE); 78 } 79} 80``` 81 82### Saving and Restoring Data 83 84After enabling **appRecovery**, you can use this function by either actively or passively saving the status and restoring data in the ability. 85The following is an example of **MainAbility**: 86 87#### Importing the Service Package 88 89```ts 90import errorManager from '@ohos.app.ability.errorManager' 91import appRecovery from '@ohos.app.ability.appRecovery' 92import AbilityConstant from '@ohos.app.ability.AbilityConstant' 93``` 94 95#### Actively Saving Status and Restoring Data 96 97- Define and register the [ErrorObserver](../reference/apis/js-apis-inner-application-errorObserver.md) callback. 98 99```ts 100 var registerId = -1; 101 var callback = { 102 onUnhandledException: function (errMsg) { 103 console.log(errMsg); 104 appRecovery.saveAppState(); 105 appRecovery.restartApp(); 106 } 107 } 108 109 onWindowStageCreate(windowStage) { 110 // Main window is created, set main page for this ability 111 console.log("[Demo] MainAbility onWindowStageCreate") 112 113 globalThis.registerObserver = (() => { 114 registerId = errorManager.registerErrorObserver(callback); 115 }) 116 117 windowStage.loadContent("pages/index", null); 118 } 119``` 120 121- Save data. 122 123After the callback triggers **appRecovery.saveAppState()**, **onSaveState(state, wantParams)** of **MainAbility** is triggered. 124 125```ts 126 onSaveState(state, wantParams) { 127 // Ability has called to save app data 128 console.log("[Demo] MainAbility onSaveState") 129 wantParams["myData"] = "my1234567"; 130 return AbilityConstant.onSaveResult.ALL_AGREE; 131 } 132``` 133 134- Restore data. 135 136After the callback triggers **appRecovery.restartApp()**, the application is restarted. After the restart, **onCreate(want, launchParam)** of **MainAbility** is called, and the saved data is in **parameters** of **want**. 137 138```ts 139storage: LocalStorage 140onCreate(want, launchParam) { 141 console.log("[Demo] MainAbility onCreate") 142 globalThis.abilityWant = want; 143 if (launchParam.launchReason == AbilityConstant.LaunchReason.APP_RECOVERY) { 144 this.storage = new LocalStorage(); 145 let recoveryData = want.parameters["myData"]; 146 this.storage.setOrCreate("myData", recoveryData); 147 this.context.restoreWindowStage(this.storage); 148 } 149} 150``` 151 152- Unregister the **ErrorObserver** callback. 153 154```ts 155onWindowStageDestroy() { 156 // Main window is destroyed, release UI related resources 157 console.log("[Demo] MainAbility onWindowStageDestroy") 158 159 globalThis.unRegisterObserver = (() => { 160 errorManager.unregisterErrorObserver(registerId, (result) => { 161 console.log("[Demo] result " + result.code + ";" + result.message) 162 }); 163 }) 164} 165``` 166 167#### Passively Saving Status and Restoring Data 168 169This is triggered by the recovery framework. You do not need to register an **ErrorObserver** callback. You only need to implement **onSaveState** of the ability for status saving and **onCreate** of the ability for data restoration. 170 171```ts 172export default class MainAbility extends Ability { 173 storage: LocalStorage 174 onCreate(want, launchParam) { 175 console.log("[Demo] MainAbility onCreate") 176 globalThis.abilityWant = want; 177 if (launchParam.launchReason == AbilityConstant.LaunchReason.APP_RECOVERY) { 178 this.storage = new LocalStorage(); 179 let recoveryData = want.parameters["myData"]; 180 this.storage.setOrCreate("myData", recoveryData); 181 this.context.restoreWindowStage(this.storage); 182 } 183 } 184 185 onSaveState(state, wantParams) { 186 // Ability has called to save app data 187 console.log("[Demo] MainAbility onSaveState") 188 wantParams["myData"] = "my1234567"; 189 return AbilityConstant.onSaveResult.ALL_AGREE; 190 } 191} 192``` 193