apprecovery-guidelines.md 10.3 KB
Newer Older
S
shawn_he 已提交
1
# Application Recovery Development
S
shawn_he 已提交
2

S
shawn_he 已提交
3
## Overview
S
shawn_he 已提交
4

S
shawn_he 已提交
5
During 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.
S
shawn_he 已提交
6

S
shawn_he 已提交
7
Process 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.
S
shawn_he 已提交
8
In 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.
S
shawn_he 已提交
9

S
shawn_he 已提交
10
Currently, the APIs support only the development of an application that adopts the stage model, single process, and single ability.
S
shawn_he 已提交
11 12 13

## Available APIs

S
shawn_he 已提交
14
The 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.
S
shawn_he 已提交
15 16 17

### Available APIs

S
shawn_he 已提交
18 19
| API                                                      | Description                                                |
| ------------------------------------------------------------ | ---------------------------------------------------- |
S
shawn_he 已提交
20 21 22
| enableAppRecovery(restart?: RestartFlag, saveOccasion?: SaveOccasionFlag, saveMode?: SaveModeFlag) : void; | Enables the application recovery function.|
| saveAppState(): boolean; | Saves the ability status of an application. |
| 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.|
S
shawn_he 已提交
23

S
shawn_he 已提交
24
The APIs are used for troubleshooting and do not return any exception. Therefore, you need to be familiar with when they are used.
S
shawn_he 已提交
25 26 27

**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).

S
shawn_he 已提交
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.
S
shawn_he 已提交
29

S
shawn_he 已提交
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.
S
shawn_he 已提交
31 32

### Framework Fault Management
S
shawn_he 已提交
33 34 35

Fault 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.

S
shawn_he 已提交
36 37 38
- 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.

- Fault rectification refers to the process of restoring the application state and data through [appRecovery](../reference/apis/js-apis-app-ability-appRecovery.md).
S
shawn_he 已提交
39

S
shawn_he 已提交
40
- Fault query is the process of calling APIs of [faultLogger](../reference/apis/js-apis-faultLogger.md) to obtain the fault information.
S
shawn_he 已提交
41

S
shawn_he 已提交
42
The 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.
S
shawn_he 已提交
43

S
shawn_he 已提交
44
![Fault rectification process](./figures/fault_rectification.png)
S
shawn_he 已提交
45

S
shawn_he 已提交
46 47 48
It 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.
If 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.
If 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.
S
shawn_he 已提交
49

S
shawn_he 已提交
50
### Supported Application Recovery Scenarios
S
shawn_he 已提交
51 52 53

Common 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.

S
shawn_he 已提交
54 55 56
| Fault  | Fault Listening | State Saving| Automatic Restart| Log Query|
| ----------|--------- |--------- |--------- |--------- |
| [JS_CRASH](../reference/apis/js-apis-faultLogger.md#faulttype) | Supported|Supported|Supported|Supported|
S
shawn_he 已提交
57
| [APP_FREEZE](../reference/apis/js-apis-faultLogger.md#faulttype) | Not supported|Not supported|Supported|Supported|
S
shawn_he 已提交
58
| [CPP_CRASH](../reference/apis/js-apis-faultLogger.md#faulttype) | Not supported|Not supported|Not supported|Supported|
S
shawn_he 已提交
59

S
shawn_he 已提交
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.
S
shawn_he 已提交
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85



## Development Example

### Enabling Application Recovery

   Enable **appRecovery** during application initialization. The following is an example of **AbilityStage**:

```ts
import AbilityStage from '@ohos.app.ability.AbilityStage'
import appRecovery from '@ohos.app.ability.appRecovery'

export default class MyAbilityStage extends AbilityStage {
    onCreate() {
        console.info("[Demo] MyAbilityStage onCreate")
        appRecovery.enableAppRecovery(appRecovery.RestartFlag.ALWAYS_RESTART,
            appRecovery.SaveOccasionFlag.SAVE_WHEN_ERROR | appRecovery.SaveOccasionFlag.SAVE_WHEN_BACKGROUND,
            appRecovery.SaveModeFlag.SAVE_WITH_FILE);
    }
}
```

### Saving and Restoring Data

S
shawn_he 已提交
86
After enabling **appRecovery**, you can use this function by either actively or passively saving the application state and restoring data in the ability.
S
shawn_he 已提交
87
The following is an example of **MainAbility**:
S
shawn_he 已提交
88 89 90 91

#### Importing the Service Package

```ts
S
shawn_he 已提交
92 93 94
import errorManager from '@ohos.app.ability.errorManager'
import appRecovery from '@ohos.app.ability.appRecovery'
import AbilityConstant from '@ohos.app.ability.AbilityConstant'
S
shawn_he 已提交
95 96
```

S
shawn_he 已提交
97
#### Actively Saving the Application State and Restoring Data
S
shawn_he 已提交
98

S
shawn_he 已提交
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).
S
shawn_he 已提交
100 101 102 103

```ts
  var registerId = -1;
  var callback = {
S
shawn_he 已提交
104
      onUnhandledException(errMsg) {
S
shawn_he 已提交
105 106 107 108 109 110 111
          console.log(errMsg);
          appRecovery.saveAppState();
          appRecovery.restartApp();
      }
  }

  onWindowStageCreate(windowStage) {
S
shawn_he 已提交
112
      // Main window is created, set main page for this ability
S
shawn_he 已提交
113
      console.log("[Demo] MainAbility onWindowStageCreate")
S
shawn_he 已提交
114 115

      globalThis.registerObserver = (() => {
S
shawn_he 已提交
116
          registerId = errorManager.on('error', callback);
S
shawn_he 已提交
117 118 119 120 121 122 123 124
      })

      windowStage.loadContent("pages/index", null);
  }
```

- Save data.

S
shawn_he 已提交
125
After the callback triggers **appRecovery.saveAppState()**, **onSaveState(state, wantParams)** of **MainAbility** is triggered.
S
shawn_he 已提交
126 127 128

```ts
  onSaveState(state, wantParams) {
S
shawn_he 已提交
129
      // Ability has called to save app data
S
shawn_he 已提交
130
      console.log("[Demo] MainAbility onSaveState")
S
shawn_he 已提交
131
      wantParams["myData"] = "my1234567";
S
shawn_he 已提交
132
      return AbilityConstant.OnSaveResult.ALL_AGREE;
S
shawn_he 已提交
133 134 135 136 137
  }
```

- Restore data.

S
shawn_he 已提交
138
After 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**.
S
shawn_he 已提交
139 140 141 142

```ts
storage: LocalStorage
onCreate(want, launchParam) {
S
shawn_he 已提交
143
    console.log("[Demo] MainAbility onCreate")
S
shawn_he 已提交
144 145 146 147 148 149 150 151 152 153
    globalThis.abilityWant = want;
    if (launchParam.launchReason == AbilityConstant.LaunchReason.APP_RECOVERY) {
        this.storage = new LocalStorage();
        let recoveryData = want.parameters["myData"];
        this.storage.setOrCreate("myData", recoveryData);
        this.context.restoreWindowStage(this.storage);
    }
}
```

S
shawn_he 已提交
154
- Unregister the **ErrorObserver** callback.
S
shawn_he 已提交
155 156 157

```ts
onWindowStageDestroy() {
S
shawn_he 已提交
158
    // Main window is destroyed, release UI related resources
S
shawn_he 已提交
159
    console.log("[Demo] MainAbility onWindowStageDestroy")
S
shawn_he 已提交
160 161

    globalThis.unRegisterObserver = (() => {
S
shawn_he 已提交
162 163
        errorManager.off('error', registerId, (err) => {
            console.error("[Demo] err:", err);
S
shawn_he 已提交
164 165 166 167 168
        });
    })
}
```

S
shawn_he 已提交
169
#### Passively Saving the Application State and Restoring Data
S
shawn_he 已提交
170

S
shawn_he 已提交
171
This 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.
S
shawn_he 已提交
172 173

```ts
S
shawn_he 已提交
174
export default class MainAbility extends Ability {
S
shawn_he 已提交
175 176
    storage: LocalStorage
    onCreate(want, launchParam) {
S
shawn_he 已提交
177
        console.log("[Demo] MainAbility onCreate")
S
shawn_he 已提交
178 179 180 181 182 183 184 185 186 187
        globalThis.abilityWant = want;
        if (launchParam.launchReason == AbilityConstant.LaunchReason.APP_RECOVERY) {
            this.storage = new LocalStorage();
            let recoveryData = want.parameters["myData"];
            this.storage.setOrCreate("myData", recoveryData);
            this.context.restoreWindowStage(this.storage);
        }
    }

    onSaveState(state, wantParams) {
S
shawn_he 已提交
188
        // Ability has called to save app data
S
shawn_he 已提交
189
        console.log("[Demo] MainAbility onSaveState")
S
shawn_he 已提交
190
        wantParams["myData"] = "my1234567";
S
shawn_he 已提交
191
        return AbilityConstant.OnSaveResult.ALL_AGREE;
S
shawn_he 已提交
192 193 194
    }
}
```