openharmony 鸿蒙 app-file-backup-sys

2026-08-25 浏览 (1)

应用触发数据备份/恢复(仅对系统应用开放)

备份恢复框架是为设备上的应用、服务提供自身数据备份和恢复的解决方案。系统应用开发者可以根据需求,按下述指导开发应用,以触发备份/恢复数据。

  • 获取能力文件:获取当前系统用户内所有应用与备份恢复相关基础信息的能力文件。能力文件在应用备份/恢复数据时不可缺少。

  • 应用备份数据:根据能力文件提供的应用信息,选择需要备份的应用数据并进行备份。

  • 应用恢复数据:根据能力文件提供的应用信息,选择需要恢复的应用数据并进行恢复。

开发说明

备份恢复API的使用指导请参见API参考

在使用备份恢复接口之前,需要:

  1. 申请应用权限ohos.permission.BACKUP

  2. 导入依赖模块:@ohos.file.backup

    import { backup } from '@kit.CoreFileKit';
    

获取能力文件

获取当前系统用户内所有应用与备份恢复相关基础信息的能力文件。能力文件在应用备份恢复数据时是不可缺少的,开发者可以根据需要获取能力文件。

该文件包含设备类型、设备版本、应用的基础性信息。如应用名称、应用数据大小、应用版本信息、是否支持备份恢复、是否在恢复时安装应用。

调用backup.getLocalCapabilities()获取能力文件。

import { fileIo } from '@kit.CoreFileKit';
import { backup } from '@kit.CoreFileKit';
import { BusinessError } from '@kit.BasicServicesKit';
// ...

// 此处仅为示例,在组件中可以通过getHostContext获取路径
let filesDir = '/data/storage/el2/base/haps/entry/files';

// 获取能力文件
export async function getLocalCapabilities(): Promise<void> {
  try {
    let fileData = await backup.getLocalCapabilities();
    console.info('getLocalCapabilities success');
    let fpath = filesDir + '/localCapabilities.json';
    fileIo.copyFileSync(fileData.fd, fpath);
    // ...
    fileIo.closeSync(fileData.fd);
  } catch (error) {
    console.error(`getLocalCapabilities failed with err, code is ${error.code}, message is ${error.message}`);
  }
}

返回的能力文件内容示例:

属性名称数据类型必填含义
bundleInfos数组应用信息列表。
allToBackup布尔值是否允许备份恢复。true表示允许,false表示不允许。
extensionName字符串应用的扩展名。
name字符串应用的包名。
spaceOccupied数值应用数据占用的空间大小(单位为Byte)。
versionCode数值应用的版本号。
versionName字符串应用的版本名称。
deviceType字符串设备类型。
systemFullName字符串设备版本。
{
"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"
}

应用备份数据

开发者可以根据能力文件提供的应用信息,选择需要备份的应用数据。

备份过程中,备份恢复服务会将应用的数据打包成文件,打包后的文件会以打开的文件句柄形式,通过创建实例时所注册的回调onFileReady接口返回。

开发者可以根据需要将文件内容保存到本地。

示例

import { fileIo } from '@kit.CoreFileKit';
import { backup } from '@kit.CoreFileKit';
import { BusinessError } from '@kit.BasicServicesKit';
// ...

// 此处仅为示例,在组件中可以通过getHostContext获取路径
let filesDir = '/data/storage/el2/base/haps/entry/files';

// ...

// 应用备份数据
// 创建SessionBackup类的实例用于备份数据
let gSession: backup.SessionBackup;

function createSessionBackup(): backup.SessionBackup {
  let generalCallbacks: backup.GeneralCallbacks = {
    // onFileReady为服务回调给应用侧数据完成的通知,建议开发者在该接口内不要进行过多的耗时实现,可以通过异步线程实现file.fd数据的处理
    onFileReady: (err: BusinessError, file: backup.File) => {
      if (err) {
        console.error(`onFileReady err, code is ${err.code}, message is ${err.message}`);
      }
      try {
        let bundlePath = filesDir + '/' + file.bundleName;
        if (!fileIo.accessSync(bundlePath)) {
          fileIo.mkdirSync(bundlePath);
        }
        // 此处执行copyFileSync会多一次内存拷贝,开发者可以直接使用onFileReady的file.fd来进行数据处理,处理完成后close即可,这样会减少内存消耗
        fileIo.copyFileSync(file.fd, bundlePath + `/${file.uri}`);
        fileIo.closeSync(file.fd);
        console.info('onFileReady success');
      } catch (error) {
        let err: BusinessError = error as BusinessError;
        console.error(`onFileReady failed. Code: ${err.code}, message: ${err.message}`);
      }
    },
    onBundleBegin: (err: BusinessError<string|void>, bundleName: string) => {
      if (err) {
        console.error(`onBundleBegin err, code is ${err.code}, message is ${err.message}`);
      } else {
        console.info('onBundleBegin bundleName: ' + bundleName);
      }
    },
    onBundleEnd: (err: BusinessError<string|void>, bundleName: string) => {
      if (err) {
        console.error(`onBundleEnd err, code is ${err.code}, message is ${err.message}`);
      } else {
        console.info('onBundleEnd bundleName: ' + bundleName);
      }
    },
    onAllBundlesEnd: (err: BusinessError) => {
      if (err) {
        console.error(`onAllBundlesEnd err, code is ${err.code}, message is ${err.message}`);
      } else {
        console.info('onAllBundlesEnd');
      }
    },
    onBackupServiceDied: () => {
      console.info('onBackupServiceDied');
    },
    onResultReport: (bundleName: string, result: string) => {
      console.info('onResultReport  bundleName: ' + bundleName);
      console.info('onResultReport  result: ' + result);
    },
    onProcess: (bundleName: string, process: string) => {
      console.info('onProcess bundleName: ' + bundleName);
      console.info('onProcess result: ' + process);
    }
  }
  let sessionBackup = new backup.SessionBackup(generalCallbacks);
  return sessionBackup;
}

// ...
export async function sessionBackup(): Promise<void> {
  gSession = createSessionBackup();
  // 此处可根据backup.getLocalCapabilities()提供的能力文件,选择需要备份的应用
  // 也可直接根据应用包名称进行备份
  const backupApps: string[] = [
    'com.samples.filebackupextension',
  ]
  await gSession.appendBundles(backupApps);
  console.info('appendBundles success');
}

应用恢复数据

开发者可以根据能力文件提供的应用信息,选择需要恢复的应用数据。

恢复过程中,备份恢复服务会根据开发者调用getFileHandle的请求内容,将应用待恢复数据的文件句柄,通过创建实例时注册的回调onFileReady接口返回。可以根据返回的uri将应用对应的待恢复数据写入到文件句柄中。写入完成后开发者调用publishFile通知服务写入完成。

待应用所有恢复数据准备就绪后,服务开始恢复应用数据。

示例

import { fileIo } from '@kit.CoreFileKit';
import { backup } from '@kit.CoreFileKit';
import { BusinessError } from '@kit.BasicServicesKit';
// ...

// 此处仅为示例,在组件中可以通过getHostContext获取路径
let filesDir = '/data/storage/el2/base/haps/entry/files';

// ...
// 应用数据恢复
// 创建SessionRestore类的实例用于恢复数据
let gSessionRestore: backup.SessionRestore;
let initMap = new Map<string, number>();
let testFileNum = 2; // 初始化文件个数
let testBundleName = 'com.samples.filebackupextension'; // 测试包名
initMap.set(testBundleName, testFileNum);
let countMap = new Map<string, number>();
countMap.set(testBundleName, 0); // 初始化计数

async function publishFile(file: backup.File): Promise<void> {
  console.info('start publishFile');
  let fileMeta: backup.FileMeta = {
    bundleName: file.bundleName,
    uri: ''
  }
  await gSessionRestore.publishFile(fileMeta);
}

function createSessionRestore(): backup.SessionRestore {
  let generalCallbacks: backup.GeneralCallbacks = {
    onFileReady: (err: BusinessError, file: backup.File) => {
      if (err) {
        console.error(`onFileReady err, code is ${err.code}, message is ${err.message}`);
      }
      // 此处开发者请根据实际场景待恢复文件存放位置进行调整 bundlePath
      let bundlePath: string = `${filesDir}/${file.bundleName}/`;
      if (!fileIo.accessSync(bundlePath)) {
        console.error('onFileReady bundlePath err : ' + bundlePath);
      }
      console.info('fd : ' + file.fd);
      let targetPath = `${bundlePath}${file.uri}`;
      fileIo.copyFileSync(targetPath, file.fd);
      fileIo.closeSync(file.fd);
      let currentCount = countMap.get(file.bundleName)||0; // 如果没有找到对应的计数,则默认返回 0
      countMap.set(file.bundleName, ++currentCount);
      // 恢复数据传输完成后,会通知服务端文件准备就绪
      if (countMap.get(file.bundleName) == initMap.get(file.bundleName)) { // 每个包的所有文件收到后触发publishFile
        publishFile(file);
      }
      console.info('onFileReady success');
    },
    onBundleBegin: (err: BusinessError<string|void>, bundleName: string) => {
      if (err) {
        console.error(`onBundleBegin failed with err, code is ${err.code}, message is ${err.message}`);
      }
      console.info('onBundleBegin success');
    },
    onBundleEnd: (err: BusinessError<string|void>, bundleName: string) => {
      if (err) {
        console.error(`onBundleEnd failed with err, code is ${err.code}, message is ${err.message}`);
      }
      console.info('onBundleEnd success');
    },
    onAllBundlesEnd: (err: BusinessError) => {
      if (err) {
        console.error(`onAllBundlesEnd failed with err, code is ${err.code}, message is ${err.message}`);
      }
      console.info('onAllBundlesEnd success');
    },
    onBackupServiceDied: () => {
      console.info('service died');
    },
    onResultReport: (bundleName: string, result: string) => {
      console.info('onResultReport  bundleName: ' + bundleName);
      console.info('onResultReport  result: ' + result);
    },
    onProcess: (bundleName: string, process: string) => {
      console.info('onProcess bundleName: ' + bundleName);
      console.info('onProcess result: ' + process);
    }
  }
  let sessionRestore = new backup.SessionRestore(generalCallbacks);
  return sessionRestore;
}

export async function sessionRestore(): Promise<void> {
  gSessionRestore = createSessionRestore();
  const restoreApps: string[] = [
    'com.samples.filebackupextension'
  ];
  // 能力文件的获取方式可以根据开发者实际场景进行调整。此处仅为请求示例
  // 开发者也可以根据能力文件内容的结构示例,自行构造能力文件内容
  let fileDat = await backup.getLocalCapabilities();
  await gSessionRestore.appendBundles(fileDat.fd, restoreApps);
  console.info('appendBundles success');
  // 添加需要恢复的应用成功后,请根据需要恢复的应用名称,调用getFileHandle接口获取待恢复应用数文件的文件句柄
  // 应用待恢复数据文件数请依据实际备份文件个数为准,此处仅为请求示例
  let handle: backup.FileMeta = {
    bundleName: restoreApps[0],
    uri: 'manage.json'
  };
  await gSessionRestore.getFileHandle(handle);
  handle.uri = 'part.0.tar';
  await gSessionRestore.getFileHandle(handle);
  console.info('getFileHandle success');
}

你可能感兴趣的鸿蒙文章

openharmony 鸿蒙 native-fileshare-guidelines

openharmony 鸿蒙 manage-external-storage-sys

openharmony 鸿蒙 file-persistPermission

openharmony 鸿蒙 app-file-backup-extension

openharmony 鸿蒙 request-dir-permission

openharmony 鸿蒙 user-file-overview

openharmony 鸿蒙 select-user-file

openharmony 鸿蒙 app-file-backup-overview

openharmony 鸿蒙 file-access-across-devices

openharmony 鸿蒙 share-app-file

  • 所属分类: 后端技术
  • 本文标签: 鸿蒙 软件
  • 版权声明: 本文链接 https://seaxiang.com/blog/b1vDU1LL