• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Backup and Restore Triggered by System Applications
2<!--Kit: Core File Kit-->
3<!--Subsystem: FileManagement-->
4<!--Owner: @lvzhenjie-->
5<!--Designer: @wang_zhangjun; @chenxi0605-->
6<!--Tester: @liuhonggang123-->
7<!--Adviser: @foryourself-->
8
9The backup and restore framework provides a solution for backing up and restoring data of applications and services on a device. You can follow the procedure below to enable an application to trigger data backup or restoration:
10
11- [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.
12
13- [Back up application data](#backing-up-application-data): Back up the application data based on the application information in the capability files.
14
15- [Restore application data](#restoring-application-data): Restore the application data based on the application information in the capability files.
16
17## How to Develop
18
19For details about how to use the APIs, see [Backup and Restore](../reference/apis-core-file-kit/js-apis-file-backup-sys.md).
20
21Before using the APIs, you need to:
22
231. Apply for the ohos.permission.BACKUP permission. For details, see [Requesting Permissions for system_basic Applications](../security/AccessToken/determine-application-mode.md#requesting-permissions-for-system_basic-applications).
24
252. Import **@ohos.file.backup**.
26
27   ```js
28   import { backup } from '@kit.CoreFileKit';
29   ```
30
31## Obtaining Capability Files
32
33Obtain capability files of all applications of the current user. The capability files are indispensable for application data backup and restoration.
34
35The 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.
36
37Call [backup.getLocalCapabilities()](../reference/apis-core-file-kit/js-apis-file-backup-sys.md#backupgetlocalcapabilities) to obtain the capability file.
38
39```ts
40import { fileIo as fs, backup } from '@kit.CoreFileKit';
41import { common } from '@kit.AbilityKit';
42import { BusinessError } from '@kit.BasicServicesKit';
43
44// Obtain the context from the component and ensure that the return value of this.getUIContext().getHostContext() is UIAbilityContext.
45let context = this.getUIContext().getHostContext() as common.UIAbilityContext;
46async function getLocalCapabilities(context: common.UIAbilityContext): Promise<void> {
47 try {
48   let filesDir = context.filesDir;
49   let fileData = await backup.getLocalCapabilities();
50   console.info('getLocalCapabilities success');
51   let fpath = filesDir + '/localCapabilities.json';
52   fs.copyFileSync(fileData.fd, fpath);
53   fs.closeSync(fileData.fd);
54 } catch (error) {
55   let err: BusinessError = error as BusinessError;
56   console.error(`getLocalCapabilities failed with err, code is ${err.code}, message is ${err.message}`);
57 }
58}
59```
60
61**Capability file example**
62
63| Name      | Type| Mandatory| Description                  |
64| -------------- | -------- | ---- | ---------------------- |
65| bundleInfos    | Array    | Yes  | Application information.          |
66| allToBackup    | Boolean  | Yes  | Whether to allow backup and restoration. The value **true** means that backup and restoration are allowed; the value **false** means the opposite.      |
67| extensionName  | String  | Yes  | Extension name of the application.          |
68| name           | String  | Yes  | Bundle name of the application.            |
69| spaceOccupied  | Number    | Yes  | Space occupied by an application, in bytes.|
70| versionCode    | Number    | Yes  | Application version number.          |
71| versionName    | String  | Yes  | Application version name.        |
72| deviceType     | String  | Yes  | Device type.              |
73| systemFullName | String  | Yes  | Device version.              |
74
75```json
76{
77"bundleInfos" :[{
78 "allToBackup" : true,
79 "extensionName" : "BackupExtensionAbility",
80 "name" : "com.example.hiworld",
81 "needToInstall" : false,
82 "spaceOccupied" : 0,
83 "versionCode" : 1000000,
84 "versionName" : "1.0.0"
85 }],
86"deviceType" : "default",
87"systemFullName" : "OpenHarmony-4.0.0.0"
88}
89```
90
91## Backing Up Application Data
92
93You can select the application data to be backed up based on the application information in the capability files.
94
95The Backup & Restore service packages the application data to be backed up. The package file handle is returned by the [onFileReady](../reference/apis-core-file-kit/js-apis-file-backup-sys.md#onfileready) callback registered when the **SessionBackup** instance is created.
96
97You can save the file to a local directory as required.
98
99**Example**
100
101  ```ts
102  import { fileIo as fs, backup } from '@kit.CoreFileKit';
103  import { common } from '@kit.AbilityKit';
104  import { BusinessError } from '@kit.BasicServicesKit';
105  let appFileDir: string = '';
106  // Obtain the context from the component and ensure that the return value of this.getUIContext().getHostContext() is UIAbilityContext.
107  let context = this.getUIContext().getHostContext() as common.UIAbilityContext;
108  appFileDir = context.filesDir;
109  // Create a SessionBackup instance for data backup.
110  let g_session: backup.SessionBackup;
111  function createSessionBackup(fileDir: string): backup.SessionBackup {
112    let generalCallbacks: backup.GeneralCallbacks = {
113      // onFileReady is called to return a data complete notification to the application. Avoid time-consuming implementations in onFileReady. You can use asynchronous threads to process data based on the file FD.
114      onFileReady: (err: BusinessError, file: backup.File) => {
115        if (err) {
116          console.error(`onFileReady err, code is ${err.code}, message is ${err.message}`);
117        }
118        try {
119          let bundlePath = appFileDir + '/' + file.bundleName;
120          if (!fs.accessSync(bundlePath)) {
121            fs.mkdirSync(bundlePath);
122          }
123          // Calling copyFileSync causes one more memory copy. To reduce memory consumption, you can use the FD returned by onFileReady for data processing, and close the FD after data is processed.
124          fs.copyFileSync(file.fd, bundlePath + `/${file.uri}`);
125          fs.closeSync(file.fd);
126          console.info('onFileReady success');
127        } catch (e) {
128          console.error('onFileReady failed with err: ' + e);
129        }
130      },
131      onBundleBegin: (err: BusinessError<string|void>, bundleName: string) => {
132        if (err) {
133          console.error(`onBundleBegin err, code is ${err.code}, message is ${err.message}`);
134        } else {
135          console.info('onBundleBegin bundleName: ' + bundleName);
136        }
137      },
138      onBundleEnd: (err: BusinessError<string|void>, bundleName: string) => {
139        if (err) {
140          console.error(`onBundleEnd err, code is ${err.code}, message is ${err.message}`);
141        } else {
142          console.info('onBundleEnd bundleName: ' + bundleName);
143        }
144      },
145      onAllBundlesEnd: (err: BusinessError) => {
146        if (err) {
147          console.error(`onAllBundlesEnd err, code is ${err.code}, message is ${err.message}`);
148        } else {
149          console.info('onAllBundlesEnd');
150        }
151      },
152      onBackupServiceDied: () => {
153        console.info('onBackupServiceDied');
154      },
155      onResultReport: (bundleName: string, result: string) => {
156        console.info('onResultReport  bundleName: ' + bundleName);
157        console.info('onResultReport  result: ' + result);
158      },
159      onProcess:(bundleName: string, process: string) => {
160        console.info('onPross bundleName: ' + JSON.stringify(bundleName));
161        console.info('onPross result: ' + JSON.stringify(process));
162      }
163    }
164    let sessionBackup = new backup.SessionBackup(generalCallbacks);
165    return sessionBackup;
166  }
167
168  async function sessionBackup (fileDir: string): Promise<void> {
169    g_session = createSessionBackup(fileDir);
170    // Select the application to be backed up based on the capability file obtained by backup.getLocalCapabilities().
171    // You can also back up data based on the application bundle name.
172    const backupApps: string[] = [
173      "com.example.hiworld",
174    ]
175    await g_session.appendBundles(backupApps);
176    console.info('appendBundles success');
177  }
178  ```
179
180## Restoring Application Data
181
182You can select the application data to be restored based on the application information in the capability files.
183
184The Backup and Restore service returns the FD of the application data to be restored in the [onFileReady](../reference/apis-core-file-kit/js-apis-file-backup-sys.md#onfileready) callback registered when the **SessionRestore** instance is created. The file handle is obtained by [getFileHandle](../reference/apis-core-file-kit/js-apis-file-backup-sys.md#getfilehandle). Then, the data to be restored is written to the file handle based on the [uri](../reference/apis-core-file-kit/js-apis-file-backup-sys.md#filemeta) returned. After the data is written, use [publishFile](../reference/apis-core-file-kit/js-apis-file-backup-sys.md#publishfile) to notify the service that the data write is complete.
185
186When all the data of the application is ready, the service starts to restore the application data.
187
188**Example**
189
190  ```ts
191  import { backup, fileIo as fs } from '@kit.CoreFileKit';
192  import { BusinessError } from '@ohos.base';
193  // Create a SessionRestore instance for data restoration.
194  let g_session: backup.SessionRestore;
195  let initMap = new Map<string, number>();
196  testFileNum = 123; // Number of files initialized.
197  let testBundleName = 'com.example.myapplication'; // Test bundle name.
198  initMap.set(testBundleName, testFileNum);
199  let countMap = new Map<string, number>();
200  countMap.set(testBundleName, 0); // Initialization count.
201  async function publishFile(file: backup.File): Promise<void> {
202    let fileMeta: backup.FileMeta = {
203      bundleName: file.bundleName,
204      uri: ''
205    }
206    await g_session.publishFile(fileMeta);
207  }
208  function createSessionRestore(): backup.SessionRestore {
209    let generalCallbacks: backup.GeneralCallbacks = {
210      onFileReady: (err: BusinessError, file: backup.File) => {
211        if (err) {
212          console.error(`onFileReady err, code is ${err.code}, message is ${err.message}`);
213        }
214        // Set bundlePath based on the actual situation.
215        let bundlePath: string = '';
216        if (!fs.accessSync(bundlePath)) {
217          console.info('onFileReady bundlePath err : ' + bundlePath);
218        }
219        fs.copyFileSync(bundlePath, file.fd);
220        fs.closeSync(file.fd);
221        // After the data is transferred, notify the server that the files are ready.
222        let cnt = countMap.get(file.bundleName) || 0;
223        countMap.set(file.bundleName, cnt + 1);
224        if (countMap.get(file.bundleName) == initMap.get(file.bundleName)) { // Trigger publishFile after all files are received.
225          publishFile(file);
226        }
227        console.info('onFileReady success');
228      },
229      onBundleBegin: (err: BusinessError<string|void>, bundleName: string) => {
230        if (err) {
231          console.error(`onBundleBegin failed with err, code is ${err.code}, message is ${err.message}`);
232        }
233        console.info('onBundleBegin success');
234      },
235      onBundleEnd: (err: BusinessError<string|void>, bundleName: string) => {
236        if (err) {
237          console.error(`onBundleEnd failed with err, code is ${err.code}, message is ${err.message}`);
238        }
239        console.info('onBundleEnd success');
240      },
241      onAllBundlesEnd: (err: BusinessError) => {
242        if (err) {
243          console.error(`onAllBundlesEnd failed with err, code is ${err.code}, message is ${err.message}`);
244        }
245        console.info('onAllBundlesEnd success');
246      },
247      onBackupServiceDied: () => {
248        console.info('service died');
249      },
250      onResultReport: (bundleName: string, result: string) => {
251        console.info('onResultReport  bundleName: ' + bundleName);
252        console.info('onResultReport  result: ' + result);
253      },
254      onProcess:(bundleName: string, process: string) => {
255        console.info('onProcess bundleName: ' + bundleName);
256        console.info('onProcess result: ' + process);
257      }
258    }
259    let sessionRestore = new backup.SessionRestore(generalCallbacks);
260    return sessionRestore;
261  }
262
263  async function restore01 (): Promise<void> {
264    g_session = createSessionRestore();
265    const restoreApps: string[] = [
266      "com.example.hiworld",
267    ]
268    // You can obtain the capability file based on actual situation. The following is an example only.
269    // You can also construct capability files as required.
270    let fileData = await backup.getLocalCapabilities();
271    await g_session.appendBundles(fileData.fd, restoreApps);
272    console.info('appendBundles success');
273    // 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.
274    // The number of application data files to be restored varies depending on the number of backup files. The following is only an example.
275    let handle: backup.FileMeta = {
276      bundleName: restoreApps[0],
277      uri: "manage.json"
278    }
279    await g_session.getFileHandle(handle);
280    handle.uri = "1.tar";
281    await g_session.getFileHandle(handle);
282    console.info('getFileHandle success');
283  }
284  ```
285