• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 recovery framework are violated.
6
7Process exit is treated as the default exception handling method. However, if user data is generated during application use, process exit 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, see [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, see [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 accepted in this API, 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
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 an [ErrorObserver](../reference/apis/js-apis-inner-application-errorObserver.md) via [errorManager](../reference/apis/js-apis-app-ability-errorManager.md), listening for faults, and notifying the listener of the faults.
37
38- Fault rectification refers to the process of restoring the application state and data through [appRecovery](../reference/apis/js-apis-app-ability-appRecovery.md).
39
40- Fault query is the process of calling APIs of [faultLogger](../reference/apis/js-apis-faultLogger.md) to obtain the fault information.
41
42The figure below does not illustrate the time when [faultLogger](../reference/apis/js-apis-faultLogger.md) is called. You can refer to the [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 information about the previous fault.
43
44![Fault rectification process](./figures/fault_rectification.png)
45
46It is recommended that you call [errorManager](../reference/apis/js-apis-app-ability-errorManager.md) to handle the exception. After the processing is complete, you can call the **saveAppState** API and restart the application.
47If 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.
48If you have enabled application recovery, the recovery framework first checks whether application state saving is supported and whether the application state saving is enabled. If so, the recovery framework invokes [onSaveState](../reference/apis/js-apis-app-ability-uiAbility.md#uiabilityonsavestate) of the [Ability](../reference/apis/js-apis-app-ability-uiAbility.md). Finally, the application is restarted.
49
50### Supported Application Recovery Scenarios
51
52Common 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.
53
54| Fault  | Fault Listening | State Saving| Automatic Restart| Log Query|
55| ----------|--------- |--------- |--------- |--------- |
56| [JS_CRASH](../reference/apis/js-apis-faultLogger.md#faulttype) | Supported|Supported|Supported|Supported|
57| [APP_FREEZE](../reference/apis/js-apis-faultLogger.md#faulttype) | Not supported|Not supported|Supported|Supported|
58| [CPP_CRASH](../reference/apis/js-apis-faultLogger.md#faulttype) | Not supported|Not supported|Not supported|Supported|
59
60**State Saving** in the table header means saving of the application state when a fault occurs. To protect user data as much as possible when an AppFreeze occurs, you can adopt either the periodic or automatic way, and the latter will save user data when an ability is switched to the background.
61
62
63
64## Development Example
65
66### Enabling Application Recovery
67
68   Enable **appRecovery** during application initialization. The following is an example of **AbilityStage**:
69
70```ts
71import AbilityStage from '@ohos.app.ability.AbilityStage'
72import appRecovery from '@ohos.app.ability.appRecovery'
73
74export default class MyAbilityStage extends AbilityStage {
75    onCreate() {
76        console.info("[Demo] MyAbilityStage onCreate")
77        appRecovery.enableAppRecovery(appRecovery.RestartFlag.ALWAYS_RESTART,
78            appRecovery.SaveOccasionFlag.SAVE_WHEN_ERROR | appRecovery.SaveOccasionFlag.SAVE_WHEN_BACKGROUND,
79            appRecovery.SaveModeFlag.SAVE_WITH_FILE);
80    }
81}
82```
83
84### Saving and Restoring Data
85
86After enabling **appRecovery**, you can use this function by either actively or passively saving the application state and restoring data in the ability.
87The following is an example of **MainAbility**:
88
89#### Importing the Service Package
90
91```ts
92import errorManager from '@ohos.app.ability.errorManager'
93import appRecovery from '@ohos.app.ability.appRecovery'
94import AbilityConstant from '@ohos.app.ability.AbilityConstant'
95```
96
97#### Actively Saving the Application State and Restoring Data
98
99- Define and register the [ErrorObserver](../reference/apis/js-apis-inner-application-errorObserver.md) callback. For details about its usage, see [errorManager](../reference/apis/js-apis-app-ability-errorManager.md).
100
101```ts
102  var registerId = -1;
103  var callback = {
104      onUnhandledException(errMsg) {
105          console.log(errMsg);
106          appRecovery.saveAppState();
107          appRecovery.restartApp();
108      }
109  }
110
111  onWindowStageCreate(windowStage) {
112      // Main window is created, set main page for this ability
113      console.log("[Demo] MainAbility onWindowStageCreate")
114
115      globalThis.registerObserver = (() => {
116          registerId = errorManager.on('error', callback);
117      })
118
119      windowStage.loadContent("pages/index", null);
120  }
121```
122
123- Save data.
124
125After the callback triggers **appRecovery.saveAppState()**, **onSaveState(state, wantParams)** of **MainAbility** is triggered.
126
127```ts
128  onSaveState(state, wantParams) {
129      // Ability has called to save app data
130      console.log("[Demo] MainAbility onSaveState")
131      wantParams["myData"] = "my1234567";
132      return AbilityConstant.OnSaveResult.ALL_AGREE;
133  }
134```
135
136- Restore data.
137
138After 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**.
139
140```ts
141storage: LocalStorage
142onCreate(want, launchParam) {
143    console.log("[Demo] MainAbility onCreate")
144    globalThis.abilityWant = want;
145    if (launchParam.launchReason == AbilityConstant.LaunchReason.APP_RECOVERY) {
146        this.storage = new LocalStorage();
147        let recoveryData = want.parameters["myData"];
148        this.storage.setOrCreate("myData", recoveryData);
149        this.context.restoreWindowStage(this.storage);
150    }
151}
152```
153
154- Unregister the **ErrorObserver** callback.
155
156```ts
157onWindowStageDestroy() {
158    // Main window is destroyed, release UI related resources
159    console.log("[Demo] MainAbility onWindowStageDestroy")
160
161    globalThis.unRegisterObserver = (() => {
162        errorManager.off('error', registerId, (err) => {
163            console.error("[Demo] err:", err);
164        });
165    })
166}
167```
168
169#### Passively Saving the Application State and Restoring Data
170
171This is triggered by the recovery framework. You do not need to register an **ErrorObserver** callback. You only need to implement **onSaveState** for application state saving and **onCreate** for data restore.
172
173```ts
174export default class MainAbility extends Ability {
175    storage: LocalStorage
176    onCreate(want, launchParam) {
177        console.log("[Demo] MainAbility onCreate")
178        globalThis.abilityWant = want;
179        if (launchParam.launchReason == AbilityConstant.LaunchReason.APP_RECOVERY) {
180            this.storage = new LocalStorage();
181            let recoveryData = want.parameters["myData"];
182            this.storage.setOrCreate("myData", recoveryData);
183            this.context.restoreWindowStage(this.storage);
184        }
185    }
186
187    onSaveState(state, wantParams) {
188        // Ability has called to save app data
189        console.log("[Demo] MainAbility onSaveState")
190        wantParams["myData"] = "my1234567";
191        return AbilityConstant.OnSaveResult.ALL_AGREE;
192    }
193}
194```
195