app-file-backup.md 15.5 KB
Newer Older
A
Annie_wang 已提交
1
# Backup and Restoration Triggered by System Applications
A
Annie_wang 已提交
2

A
Annie_wang 已提交
3
The backup and restoration framework provides a complete data backup and restoration solution for application data, user data, and system services on devices. You can follow the procedure below to enable an application to trigger data backup or restoration:
A
Annie_wang 已提交
4

A
Annie_wang 已提交
5
- [Obtain capability files](#obtaining-capability-files): Obtain capability files of all applications of the user in the system. The capability files are indispensable for data backup and restoration.
A
Annie_wang 已提交
6

A
Annie_wang 已提交
7
- [Back up application data](#backing-up-application-data): Back up the application data based on the application information in the capability files.
A
Annie_wang 已提交
8

A
Annie_wang 已提交
9
- [Restore application data](#restoring-application-data): Restore the application data based on the application information in the capability files.
A
Annie_wang 已提交
10

A
Annie_wang 已提交
11
- [Install the application during data restoration](#installing-the-application-during-data-restoration): Install the application if the application with data to be restored has not been installed. As an extended function of application data restoration, this function allows the application to be installed on the device before data restoration.
A
Annie_wang 已提交
12 13 14 15 16 17 18

## How to Develop

For details about the APIs to be used, see [Backup and Restoration](../reference/apis/js-apis-file-backup.md).

Before using the APIs, you need to:

A
Annie_wang 已提交
19
1. Apply for the **ohos.permission.BACKUP** permission. For details, see [Apply for Permissions](../security/accesstoken-guidelines.md).
A
Annie_wang 已提交
20 21 22 23 24 25 26

2. Import **@ohos.file.backup**.
   
   ```js
   import backup from '@ohos.file.backup';
   ```

A
Annie_wang 已提交
27
## Obtaining Capability Files
A
Annie_wang 已提交
28

A
Annie_wang 已提交
29
Obtain capability files of all applications of the current user. The capability files are indispensable for application data backup and restoration.
A
Annie_wang 已提交
30

A
Annie_wang 已提交
31
The capability file of an application contains the device type, device version, and basic application information, such as the application name, application size, application version, whether to allow backup and restoration, and whether to install the application during restoration.
A
Annie_wang 已提交
32

A
Annie_wang 已提交
33
Use **backup.getLocalCapabilities()** to obtain capability files.
A
Annie_wang 已提交
34

A
Annie_wang 已提交
35 36 37
 ```ts
  import backup from '@ohos.file.backup';
  import common from '@ohos.app.ability.common';
A
Annie_wang 已提交
38
  import fs from '@ohos.file.fs';
A
Annie_wang 已提交
39 40 41 42 43

  // Obtain the application file path.
  let context = getContext(this) as common.UIAbilityContext;
  let filesDir = context.filesDir;

A
Annie_wang 已提交
44 45 46 47
  async function getLocalCapabilities() {
    try {
      let fileData = await backup.getLocalCapabilities();
      console.info('getLocalCapabilities success');
A
Annie_wang 已提交
48
      let fpath = filesDir + '/localCapabilities.json';
A
Annie_wang 已提交
49 50
      fs.copyFileSync(fileData.fd, fpath);
      fs.closeSync(fileData.fd);
A
Annie_wang 已提交
51 52 53
    } catch (error) {
      let err: BusinessError = error as BusinessError;
      console.error('getLocalCapabilities failed with err: ' + JSON.stringify(err));
A
Annie_wang 已提交
54 55 56 57 58 59 60 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 86 87 88 89
    }
  }
 ```

 **Capability file example**
 | Name      | Type| Mandatory| Description                  |
 | -------------- | -------- | ---- | ---------------------- |
 | bundleInfos    | Array    | Yes  | Application information.          |
 | allToBackup    | Boolean  | Yes  | Whether to allow backup and restoration.      |
 | extensionName  | String  | Yes  | Extension name of the application.          |
 | name           | String  | Yes  | Bundle name of the application.            |
 | needToInstall  | Boolean  | Yes  | Whether to install the application during data restoration.|
 | spaceOccupied  | Number    | Yes  | Space occupied by the application data.|
 | versionCode    | Number    | Yes  | Application version number.          |
 | versionName    | String  | Yes  | Application version name.        |
 | deviceType     | String  | Yes  | Type of the device.              |
 | systemFullName | String  | Yes  | Device version.              |

 ```json
 {
  "bundleInfos" :[{
    "allToBackup" : true,
    "extensionName" : "BackupExtensionAbility",
    "name" : "com.example.hiworld",
    "needToInstall" : false,
    "spaceOccupied" : 0,
    "versionCode" : 1000000,
    "versionName" : "1.0.0"
    }],
  "deviceType" : "default",
  "systemFullName" : "OpenHarmony-4.0.0.0"
 }
 ```

## Backing Up Application Data

A
Annie_wang 已提交
90
You can select the application data to be backed up based on the application information in the capability files.
A
Annie_wang 已提交
91

A
Annie_wang 已提交
92
The Backup & Restore service packages the application data to be backed up. The package file handle is returned by the [onFileReady](../reference/apis/js-apis-file-backup.md#onfileready) callback registered when the **SessionBackup** instance is created.
A
Annie_wang 已提交
93 94 95 96 97 98

You can save the file to a local directory as required.

**Example**

 ```ts
A
Annie_wang 已提交
99 100
  import backup from '@ohos.file.backup';
  import common from '@ohos.app.ability.common';
A
Annie_wang 已提交
101
  import fs from '@ohos.file.fs';
A
Annie_wang 已提交
102 103 104 105 106
  import { BusinessError } from '@ohos.base';

  // Obtain the sandbox path.
  let context = getContext(this) as common.UIAbilityContext;
  let filesDir = context.filesDir;
A
Annie_wang 已提交
107
  // Create a SessionBackup instance for data backup.
A
Annie_wang 已提交
108
  let g_session: backup.SessionBackup;
A
Annie_wang 已提交
109
  function createSessionBackup() {
A
Annie_wang 已提交
110 111
    let generalCallbacks: backup.GeneralCallbacks = {
      onFileReady: (err: BusinessError, file: backup.File) => {
A
Annie_wang 已提交
112
        if (err) {
A
Annie_wang 已提交
113
          console.info('onFileReady err: ' + JSON.stringify(err));
A
Annie_wang 已提交
114 115
        }
        try {
A
Annie_wang 已提交
116
          let bundlePath = filesDir + '/' + file.bundleName;
A
Annie_wang 已提交
117 118 119 120 121 122 123 124 125 126
          if (!fs.accessSync(bundlePath)) {
            fs.mkdirSync(bundlePath);
          }
          fs.copyFileSync(file.fd, bundlePath + `/${file.uri}`);
          fs.closeSync(file.fd);
          console.info('onFileReady success');
        } catch (e) {
          console.error('onFileReady failed with err: ' + e);
        }
      },
A
Annie_wang 已提交
127
      onBundleBegin: (err: BusinessError, bundleName: string) => {
A
Annie_wang 已提交
128
        if (err) {
A
Annie_wang 已提交
129
          console.info('onBundleBegin err: ' + JSON.stringify(err));
A
Annie_wang 已提交
130 131 132 133
        } else {
          console.info('onBundleBegin bundleName: ' + bundleName);
        }
      },
A
Annie_wang 已提交
134
      onBundleEnd: (err: BusinessError, bundleName: string) => {
A
Annie_wang 已提交
135
        if (err) {
A
Annie_wang 已提交
136
          console.info('onBundleEnd err: ' + JSON.stringify(err));
A
Annie_wang 已提交
137 138 139 140
        } else {
          console.info('onBundleEnd bundleName: ' + bundleName);
        }
      },
A
Annie_wang 已提交
141
      onAllBundlesEnd: (err: BusinessError) => {
A
Annie_wang 已提交
142
        if (err) {
A
Annie_wang 已提交
143
          console.info('onAllBundlesEnd err: ' + JSON.stringify(err));
A
Annie_wang 已提交
144 145 146 147 148 149 150
        } else {
          console.info('onAllBundlesEnd');
        }
      },
      onBackupServiceDied: () => {
        console.info('onBackupServiceDied');
      },
A
Annie_wang 已提交
151 152
    }
    let sessionBackup = new backup.SessionBackup(generalCallbacks);
A
Annie_wang 已提交
153 154
    return sessionBackup;
  }
A
Annie_wang 已提交
155 156

  async function sessionBackup () {
A
Annie_wang 已提交
157 158 159
    g_session = createSessionBackup();
    // Select the application to be backed up based on the capability file obtained by backup.getLocalCapabilities().
    // You can also back up data based on the application bundle name.
A
Annie_wang 已提交
160
    const backupApps: string[] = [
A
Annie_wang 已提交
161 162 163 164 165 166 167 168 169
      "com.example.hiworld",
    ]
    await g_session.appendBundles(backupApps);
    console.info('appendBundles success');
  }
 ```

## Restoring Application Data

A
Annie_wang 已提交
170
You can select the application data to be restored based on the application information in the capability files.
A
Annie_wang 已提交
171

A
Annie_wang 已提交
172
The Backup and Restore service returns the file handle of the application data to be restored in the [onFileReady](../reference/apis/js-apis-file-backup.md#onfileready) callback registered when the **SessionRestore** instance is created. The file handle is obtained by [getFileHandle](../reference/apis/js-apis-file-backup.md#getfilehandle). Then, the data to be restored is written to the file handle based on the [uri](../reference/apis/js-apis-file-backup.md#filemeta) returned. After the data is written, use [publishFile()](../reference/apis/js-apis-file-backup.md#publishfile) to notify the service that the data write is complete.
A
Annie_wang 已提交
173 174 175 176 177 178

When all the data of the application is ready, the service starts to restore the application data.

**Example**

 ```ts
A
Annie_wang 已提交
179
  import backup from '@ohos.file.backup';
A
Annie_wang 已提交
180
  import fs from '@ohos.file.fs';
A
Annie_wang 已提交
181
  import { BusinessError } from '@ohos.base';
A
Annie_wang 已提交
182
  // Create a SessionRestore instance for data restoration.
A
Annie_wang 已提交
183 184 185
  let g_session: backup.SessionRestore;
  async function publishFile(file: backup.File) {
    let fileMeta: backup.FileMeta = {
A
Annie_wang 已提交
186 187
      bundleName: file.bundleName,
      uri: file.uri
A
Annie_wang 已提交
188 189
    }
    await g_session.publishFile(fileMeta);
A
Annie_wang 已提交
190 191
  }
  function createSessionRestore() {
A
Annie_wang 已提交
192 193
    let generalCallbacks: backup.GeneralCallbacks = {
      onFileReady: (err: BusinessError, file: backup.File) => {
A
Annie_wang 已提交
194
        if (err) {
A
Annie_wang 已提交
195
          console.info('onFileReady err: ' + JSON.stringify(err));
A
Annie_wang 已提交
196 197
        }
        // Set bundlePath based on the actual situation.
A
Annie_wang 已提交
198
        let bundlePath: string;
A
Annie_wang 已提交
199 200 201 202 203
        if (!fs.accessSync(bundlePath)) {
          console.info('onFileReady bundlePath err : ' + bundlePath);
        }
        fs.copyFileSync(bundlePath, file.fd);
        fs.closeSync(file.fd);
A
Annie_wang 已提交
204
        // After the data is transferred, notify the server that the files are ready.
A
Annie_wang 已提交
205 206 207
        publishFile(file);
        console.info('onFileReady success');
      },
A
Annie_wang 已提交
208
      onBundleBegin: (err: BusinessError, bundleName: string) => {
A
Annie_wang 已提交
209
        if (err) {
A
Annie_wang 已提交
210
          console.error('onBundleBegin failed with err: ' + JSON.stringify(err));
A
Annie_wang 已提交
211 212 213
        }
        console.info('onBundleBegin success');
      },
A
Annie_wang 已提交
214
      onBundleEnd: (err: BusinessError, bundleName: string) => {
A
Annie_wang 已提交
215
        if (err) {
A
Annie_wang 已提交
216
          console.error('onBundleEnd failed with err: ' + JSON.stringify(err));
A
Annie_wang 已提交
217 218 219
        }
        console.info('onBundleEnd success');
      },
A
Annie_wang 已提交
220
      onAllBundlesEnd: (err: BusinessError) => {
A
Annie_wang 已提交
221
        if (err) {
A
Annie_wang 已提交
222
          console.error('onAllBundlesEnd failed with err: ' + JSON.stringify(err));
A
Annie_wang 已提交
223 224 225 226 227 228
        }
        console.info('onAllBundlesEnd success');
      },
      onBackupServiceDied: () => {
        console.info('service died');
      }
A
Annie_wang 已提交
229 230
    }
    let sessionRestore = new backup.SessionRestore(generalCallbacks);
A
Annie_wang 已提交
231 232
    return sessionRestore;
  }
A
Annie_wang 已提交
233 234

  async function restore01 () {
A
Annie_wang 已提交
235
    g_session = createSessionRestore();
A
Annie_wang 已提交
236
    const restoreApps: string[] = [
A
Annie_wang 已提交
237 238 239
      "com.example.hiworld",
    ]
    // You can obtain the capability file based on actual situation. The following is an example only.
A
Annie_wang 已提交
240
    // You can also construct capability files as required.
A
Annie_wang 已提交
241
    let fileData = await backup.getLocalCapabilities();
A
Annie_wang 已提交
242
    await g_session.appendBundles(fileData.fd, restoreApps);
A
Annie_wang 已提交
243
    console.info('appendBundles success');
A
Annie_wang 已提交
244
    // After the applications to be restored are added, call getFileHandle() to obtain the handles of the application files to be restored based on the application name.
A
Annie_wang 已提交
245
    // The number of application data files to be restored varies depending on the number of backup files. The following is only an example.
A
Annie_wang 已提交
246
    let handle: backup.FileMeta = {
A
Annie_wang 已提交
247 248
      bundleName: restoreApps[0],
      uri: "manage.json"
A
Annie_wang 已提交
249 250 251 252
    }
    await g_session.getFileHandle(handle);
    handle.uri = "1.tar";
    await g_session.getFileHandle(handle);
A
Annie_wang 已提交
253 254 255 256 257 258
    console.info('getFileHandle success');
  }
 ```

## Installing the Application During Data Restoration

A
Annie_wang 已提交
259
If the application has not been installed, you can install the application and then restore the application data. To achieve this purpose, the value of **needToInstall** in **bundleInfos** in the [capability file](#obtaining-capability-files) must be **true**.
A
Annie_wang 已提交
260 261 262

> **NOTE**
> - [Application data backup](#backing-up-application-data) does not support backup of the application installation package. Therefore, you need to obtain the application installation package.
A
Annie_wang 已提交
263
> - To obtain the file handle of an application installation package, call [getFileHandle()](../reference/apis/js-apis-file-backup.md#getfilehandle) with **FileMeta.uri** set to **/data/storage/el2/restore/bundle.hap**. The file handle of the application installation package is returned through the **onFileReady()** callback registered when the instance is created. The returned **File.uri** is **data/storage/el2/restore/bundle.hap**.
A
Annie_wang 已提交
264 265 266 267

**Example**

 ```ts
A
Annie_wang 已提交
268 269
  import backup from '@ohos.file.backup';
  import common from '@ohos.app.ability.common';
A
Annie_wang 已提交
270
  import fs from '@ohos.file.fs';
A
Annie_wang 已提交
271 272 273 274 275
  import { BusinessError } from '@ohos.base';

  // Obtain the sandbox path.
  let context = getContext(this) as common.UIAbilityContext;
  let filesDir = context.filesDir;
A
Annie_wang 已提交
276
  // Create a SessionRestore instance for data restoration.
A
Annie_wang 已提交
277 278 279
  let g_session: backup.SessionRestore;
  async function publishFile(file: backup.File) {
    let fileMeta: backup.FileMeta = {
A
Annie_wang 已提交
280 281
      bundleName: file.bundleName,
      uri: file.uri
A
Annie_wang 已提交
282 283
    }
    await g_session.publishFile(fileMeta);
A
Annie_wang 已提交
284 285
  }
  function createSessionRestore() {
A
Annie_wang 已提交
286 287 288 289 290 291
    let generalCallbacks: backup.GeneralCallbacks = {
      onFileReady: (err: BusinessError, file: backup.File) => {
        if (err) {
          console.info('onFileReady err: ' + JSON.stringify(err));
        }
        let bundlePath: string;
A
Annie_wang 已提交
292 293 294 295 296 297 298 299 300 301 302
        if( file.uri == "/data/storage/el2/restore/bundle.hap" )
        {
          // Set the path of the application installation package based on actual situation.
        } else {
          // Set bundlePath based on the actual situation.
        }
        if (!fs.accessSync(bundlePath)) {
          console.info('onFileReady bundlePath err : ' + bundlePath);
        }
        fs.copyFileSync(bundlePath, file.fd);
        fs.closeSync(file.fd);
A
Annie_wang 已提交
303
        // After the data is transferred, notify the server that the files are ready.
A
Annie_wang 已提交
304 305 306
        publishFile(file);
        console.info('onFileReady success');
      },
A
Annie_wang 已提交
307
      onBundleBegin: (err: BusinessError, bundleName: string) => {
A
Annie_wang 已提交
308
        if (err) {
A
Annie_wang 已提交
309
          console.error('onBundleBegin failed with err: ' + JSON.stringify(err));
A
Annie_wang 已提交
310 311 312
        }
        console.info('onBundleBegin success');
      },
A
Annie_wang 已提交
313
      onBundleEnd: (err: BusinessError, bundleName: string) => {
A
Annie_wang 已提交
314
        if (err) {
A
Annie_wang 已提交
315
          console.error('onBundleEnd failed with err: ' + JSON.stringify(err));
A
Annie_wang 已提交
316 317 318
        }
        console.info('onBundleEnd success');
      },
A
Annie_wang 已提交
319
      onAllBundlesEnd: (err: BusinessError) => {
A
Annie_wang 已提交
320
        if (err) {
A
Annie_wang 已提交
321
          console.error('onAllBundlesEnd failed with err: ' + JSON.stringify(err));
A
Annie_wang 已提交
322 323 324 325 326 327
        }
        console.info('onAllBundlesEnd success');
      },
      onBackupServiceDied: () => {
        console.info('service died');
      }
A
Annie_wang 已提交
328 329
    }
    let sessionRestore = new backup.SessionRestore(generalCallbacks);
A
Annie_wang 已提交
330 331
    return sessionRestore;
  }
A
Annie_wang 已提交
332 333

  async function restore02 () {
A
Annie_wang 已提交
334
    g_session = createSessionRestore();
A
Annie_wang 已提交
335
    const restoreApps: string[] = [
A
Annie_wang 已提交
336 337
      "com.example.hiworld",
    ]
A
Annie_wang 已提交
338 339
    let fpath = filesDir + '/localCapabilities.json';
    let file = fs.openSync(fpath, fs.OpenMode.CREATE | fs.OpenMode.READ_WRITE);
A
Annie_wang 已提交
340 341 342 343 344
    let content = "{\"bundleInfos\" :[{\"allToBackup\" : false,\"extensionName\" : \"\"," +
    "\"name\" : \"cn.openharmony.inputmethodchoosedialog\",\"needToInstall\" : true,\"spaceOccupied\" : 0," +
    "\"versionCode\" : 1000000,\"versionName\" : \"1.0.0\"}],\"deviceType\" : \"default\",\"systemFullName\"   : \"OpenHarmony-4.0.6.2(Canary1)\"}";
    fs.writeSync(file.fd, content);
    fs.fsyncSync(file.fd);
A
Annie_wang 已提交
345
    await g_session.appendBundles(file.fd, restoreApps);
A
Annie_wang 已提交
346
    console.info('appendBundles success');
A
Annie_wang 已提交
347

A
Annie_wang 已提交
348
    // Obtain the file handle of the application to be installed.
A
Annie_wang 已提交
349
    let handle: backup.FileMeta = {
A
Annie_wang 已提交
350 351
      bundleName: restoreApps[0],
      uri: "/data/storage/el2/restore/bundle.hap"
A
Annie_wang 已提交
352 353 354 355 356 357
    }
    await g_session.getFileHandle(handle);
    handle.uri = "manage.json";
    await g_session.getFileHandle(handle);
    handle.uri = "1.tar";
    await g_session.getFileHandle(handle);
A
Annie_wang 已提交
358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377
    console.info('getFileHandle success');
  }
 ```

  **Capability file example**
 ```json
 {
  "bundleInfos" :[{
    "allToBackup" : true,
    "extensionName" : "BackupExtensionAbility",
    "name" : "com.example.hiworld",
    "needToInstall" : true,
    "spaceOccupied" : 0,
    "versionCode" : 1000000,
    "versionName" : "1.0.0"
    }],
  "deviceType" : "default",
  "systemFullName" : "OpenHarmony-4.0.0.0"
 }
 ```