使用自动备份备份用户数据

应用程序自动备份会自动备份用户针对运行在 Android 6.0(API 级别 23)或更高版本的应用程序的数据。Android 通过将应用程序数据上传到用户的 Google Drive 来保存应用程序数据,该数据在用户的 Google 帐户凭据的保护下。对于运行在 Android 9 或更高版本上的设备,备份使用设备的 PIN、图案或密码进行端到端加密。每个应用程序可以为每个应用程序用户分配最多 25 MB 的备份数据。存储备份数据不收取任何费用。您的应用程序可以自定义备份过程,也可以通过禁用备份来选择退出。

有关 Android 备份选项的概述以及有关备份和还原哪些数据的指南,请参阅数据备份概述

备份的文件

默认情况下,自动备份会包含系统分配给您的应用程序的大多数目录中的文件

自动备份会排除由 getCacheDir()getCodeCacheDir()getNoBackupFilesDir() 返回的目录中的文件。保存在这些位置的文件仅在临时需要,因此有意从备份操作中排除。

您可以配置您的应用程序以包含和排除特定文件。有关更多信息,请参阅包含和排除文件部分。

备份位置

备份数据存储在用户 Google Drive 帐户中的私有文件夹中,每个应用程序最多限于 25 MB。保存的数据不计入用户的个人 Google Drive 配额。仅存储最新的备份。备份完成后,会删除所有先前的备份。用户或设备上的其他应用程序无法读取备份数据。

用户可以在 Google Drive Android 应用程序中看到已备份应用程序的列表。在 Android 设备上,用户可以在 Drive 应用程序的导航抽屉中找到此列表,位于 **设置 > 备份和重置**下。

每个设备设置生命周期的备份都存储在单独的数据集中,如下面的示例所述

  • 如果用户拥有两台设备,则每台设备都存在一个备份数据集。

  • 如果用户将设备恢复出厂设置,然后使用相同的帐户设置设备,则备份存储在新的数据集中。过时的数据集会在一段时间不活动后自动删除。

备份计划

当满足以下所有条件时,将自动进行备份

  • 用户已在设备上启用备份。在 Android 9 中,此设置位于 **设置 > 系统 > 备份** 中。
  • 自上次备份以来已过去至少 24 小时。
  • 设备处于闲置状态。
  • 设备已连接到 Wi-Fi 网络(如果设备用户未选择加入移动数据备份)。

实际上,这些条件通常在每个晚上出现,但设备可能永远不会备份(例如,如果它从未连接到网络)。为了节省网络带宽,只有在应用程序数据发生更改时才会进行上传。

在自动备份期间,系统会关闭应用程序,以确保它不再写入文件系统。默认情况下,备份系统会忽略在前景中运行的应用程序,以避免糟糕的用户体验。您可以通过将 android:backupInForeground 属性设置为 true 来覆盖默认行为。

为了简化测试,Android 包含允许您手动启动应用程序备份的工具。有关更多信息,请参阅 测试备份和恢复

恢复计划

无论是从 Play 商店安装、在设备设置期间(当系统安装先前安装的应用程序时)还是通过运行 adb install 安装,只要应用程序安装,就会恢复数据。恢复操作发生在 APK 安装后,但在应用程序可供用户启动之前。

在初始设备设置向导期间,将向用户显示一个可用的备份数据集列表,并询问用户要从哪个数据集恢复数据。用户选择的备份数据集将成为该设备的祖先数据集。设备可以从其自己的备份或祖先数据集恢复。如果两种来源的备份都可用,设备会优先使用其自己的备份。如果用户没有执行设备设置向导,则设备只能从其自己的备份恢复。

为了简化测试,Android 包含允许您手动启动应用程序恢复的工具。有关更多信息,请参阅 测试备份和恢复

启用和禁用备份

面向 Android 6.0(API 级别 23)或更高版本的应用程序会自动参与自动备份。在您的应用程序清单文件中,将布尔值 android:allowBackup 设置为启用或禁用备份。默认值为 true,但我们建议在清单中显式设置此属性,如以下示例所示

<manifest ... >
    ...
    <application android:allowBackup="true" ... >
        ...
    </application>
</manifest>

您可以通过将 android:allowBackup 设置为 false 来禁用备份。如果您应用程序可以通过其他机制重新创建其状态,或者如果您的应用程序处理敏感信息,则可能需要这样做。

包含和排除文件

默认情况下,系统会备份几乎所有应用程序数据。有关更多信息,请参阅有关 备份的文件 的部分。

本节将向您展示如何定义自定义 XML 规则以控制备份的内容。如果您的应用程序面向 Android 12(API 级别 31)或更高版本,则必须 指定一组额外的 XML 备份规则(如本节所述),以支持针对运行这些 Android 版本的设备引入的 备份恢复变更

控制 Android 11 及更低版本的备份

按照本节中的步骤来控制在运行 Android 11(API 级别 30)或更低版本的设备上备份哪些文件。

  1. 在您的 AndroidManifest.xml 文件中,将 android:fullBackupContent 属性添加到 <application> 元素中,如以下示例所示。此属性指向包含备份规则的 XML 文件。

    <application ...
     android:fullBackupContent="@xml/backup_rules">
    </application>
    
  2. res/xml/ 目录中创建一个名为 @xml/backup_rules 的 XML 文件。在此文件中,使用 <include><exclude> 元素添加规则。以下示例会备份除 device.xml 之外的所有共享首选项

    <?xml version="1.0" encoding="utf-8"?>
    <full-backup-content>
     <include domain="sharedpref" path="."/>
     <exclude domain="sharedpref" path="device.xml"/>
    </full-backup-content>
    

定义备份所需设备条件

如果您的应用程序在设备上保存了敏感信息,您可以指定在哪些条件下您的应用程序数据包含在用户的备份中。您可以在 Android 9(API 级别 28)或更高版本中添加以下条件

如果您已将您的开发设备升级到 Android 9,则需要在升级后禁用并重新启用数据备份。这是因为 Android 仅在向用户告知设置或设置向导后,才使用客户端端密钥加密备份。

要声明包含条件,请在备份规则集中,将 requireFlags 属性设置为您的选择值。

backup_rules.xml

<?xml version="1.0" encoding="utf-8"?>
<full-backup-content>
    <!-- App data isn't included in user's backup
         unless client-side encryption is enabled. -->
    <include domain="file" path="."
             requireFlags="clientSideEncryption" />
</full-backup-content>

如果您的应用程序实现了 键值备份 系统,或者如果您 自己实现了 BackupAgent,您还可以通过对 BackupDataOutput 对象的传输标志集和您的自定义备份代理的 FLAG_CLIENT_SIDE_ENCRYPTION_ENABLEDFLAG_DEVICE_TO_DEVICE_TRANSFER 标志进行按位比较,将这些条件要求应用到您的备份逻辑。

以下代码片段展示了此方法的示例用法

Kotlin

class CustomBackupAgent : BackupAgent() {
    override fun onBackup(oldState: ParcelFileDescriptor?,
            data: BackupDataOutput?, newState: ParcelFileDescriptor?) {
        if (data != null) {
            if ((data.transportFlags and
                    FLAG_CLIENT_SIDE_ENCRYPTION_ENABLED) != 0) {
                // Client-side backup encryption is enabled.
            }

            if ((data.transportFlags and FLAG_DEVICE_TO_DEVICE_TRANSFER) != 0) {
                // Local device-to-device transfer is enabled.
            }
        }
    }

    // Implementation of onRestore() here.
}

Java

public class CustomBackupAgent extends BackupAgent {
    @Override
    public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
            ParcelFileDescriptor newState) throws IOException {
        if ((data.getTransportFlags() &
                FLAG_CLIENT_SIDE_ENCRYPTION_ENABLED) != 0) {
            // Client-side backup encryption is enabled.
        }

        if ((data.getTransportFlags() &
                FLAG_DEVICE_TO_DEVICE_TRANSFER) != 0) {
            // Local device-to-device transfer is enabled.
        }
    }

    // Implementation of onRestore() here.
}

控制 Android 12 或更高版本的备份

如果您的应用程序面向 Android 12(API 级别 31)或更高版本,请按照本节中的步骤来控制在运行 Android 12 或更高版本的设备上备份哪些文件。

  1. 在您的 AndroidManifest.xml 文件中,将 android:dataExtractionRules 属性添加到 <application> 元素中,如以下示例所示。此属性指向包含备份规则的 XML 文件。

    <application ...
     android:dataExtractionRules="backup_rules.xml">
    </application>
    
  2. res/xml/ 目录中创建一个名为 backup_rules.xml 的 XML 文件。在此文件中,使用 <include><exclude> 元素添加规则。以下示例会备份除 device.xml 之外的所有共享首选项

    <?xml version="1.0" encoding="utf-8"?>
    <data-extraction-rules>
     <cloud-backup [disableIfNoEncryptionCapabilities="true|false"]>
       <include domain="sharedpref" path="."/>
       <exclude domain="sharedpref" path="device.xml"/>
     </cloud-backup>
    </data-extraction-rules>
    

XML 配置语法

配置文件的 XML 语法因您的应用程序所面向和运行的 Android 版本而异。

Android 11 或更低版本

控制在运行 Android 11 或更低版本的设备上进行备份的配置文件 使用以下 XML 语法。

<full-backup-content>
    <include domain=["file" | "database" | "sharedpref" | "external" |
                     "root" | "device_file" | "device_database" |
                     "device_sharedpref" | "device_root" ] path="string"
    requireFlags=["clientSideEncryption" | "deviceToDeviceTransfer"] />
    <exclude domain=["file" | "database" | "sharedpref" | "external" |
                     "root" | "device_file" | "device_database" |
                     "device_sharedpref" | "device_root" ] path="string" />
</full-backup-content>

Android 12 或更高版本

如果您的应用程序面向 Android 12(API 级别 31)或更高版本,对 控制在运行 Android 12 或更高版本的设备上进行备份的配置文件 使用以下 XML 语法。

<data-extraction-rules>
  <cloud-backup [disableIfNoEncryptionCapabilities="true|false"]>
    ...
    <include domain=["file" | "database" | "sharedpref" | "external" |
                     "root" | "device_file" | "device_database" |
                     "device_sharedpref" | "device_root" ] path="string"/>
    ...
    <exclude domain=["file" | "database" | "sharedpref" | "external" |
                     "root" | "device_file" | "device_database" |
                     "device_sharedpref" | "device_root" ] path="string"/>
    ...
  </cloud-backup>
  <device-transfer>
    ...
    <include domain=["file" | "database" | "sharedpref" | "external" |
                     "root" | "device_file" | "device_database" |
                     "device_sharedpref" | "device_root" ] path="string"/>
    ...
    <exclude domain=["file" | "database" | "sharedpref" | "external" |
                     "root" | "device_file" | "device_database" |
                     "device_sharedpref" | "device_root" ] path="string"/>
    ...
  </device-transfer>
</data-extraction-rules>

配置的每个部分(<cloud-backup><device-transfer>)包含仅适用于该类型传输的规则。这种分离可以让您例如,从 Google 云端硬盘备份中排除文件或目录,同时在设备到设备 (D2D) 传输期间仍然传输它。如果您有太大而无法备份到云端但可以在设备之间无障碍传输的文件,这将很有用。

如果特定备份模式没有规则(例如,<device-transfer> 部分缺失),则该模式将完全启用所有内容,除了 备份的文件 一节中所述的 no-backupcache 目录。

您的应用程序可以在 <cloud-backup> 部分中设置 disableIfNoEncryptionCapabilities 标志,以确保备份仅在可以加密时进行,例如,当用户拥有锁屏时。设置此约束会阻止备份在用户设备不支持加密的情况下发送到云端,但由于 D2D 传输不会发送到服务器,因此即使在不支持加密的设备上,它们也会继续运行。

包含和排除元素的语法

<full-backup-content><cloud-backup><device-transfer> 标签(取决于设备的 Android 版本和您的应用程序的 targetSDKVersion)中,您可以定义 <include><exclude> 元素

<include>

指定要备份的文件或文件夹。默认情况下,自动备份会包含几乎所有应用程序文件。如果您指定了 <include> 元素,则系统不再默认包含任何文件,并且只备份您指定的那些文件。若要包含多个文件,请使用多个 <include> 元素。

Android 11 及更低版本 上,此元素还可以包含 requireFlags 属性,该属性在描述如何 定义备份的条件要求 的部分中有更详细的讨论。

即使尝试包含,由 getCacheDir()getCodeCacheDir()getNoBackupFilesDir() 返回的目录中的文件始终会被排除。

<exclude>

指定在备份期间要排除的文件或文件夹。以下是一些通常从备份中排除的文件

  • 包含设备特定标识符的文件,这些标识符由服务器颁发或在设备上生成。 例如,Firebase 云消息传递 (FCM) 每次用户在新设备上安装您的应用程序时都需要生成注册令牌。 如果恢复旧的注册令牌,应用程序可能会出现意外行为。

  • 与应用程序调试相关的文件。

  • 导致应用程序超过 25 MB 备份配额的大文件。

每个 <include><exclude> 元素必须包含以下两个属性

domain

指定资源的位置。 此属性的有效值包括以下内容

  • root:文件系统上存储此应用程序所有私有文件的目录。
  • file:由 getFilesDir() 返回的目录。
  • database:由 getDatabasePath() 返回的目录。 使用 SQLiteOpenHelper 创建的数据库存储在此处。
  • sharedpref:存储 SharedPreferences 的目录。
  • external:由 getExternalFilesDir() 返回的目录。
  • device_root:类似于 root,但用于设备保护存储。
  • device_file:类似于 file,但用于设备保护存储。
  • device_database:类似于 database,但用于设备保护存储。
  • device_sharedpref:类似于 sharedpref,但用于设备保护存储。
path

指定要包含在备份中或从备份中排除的文件或文件夹。 注意以下事项

  • 此属性不支持通配符或正则表达式语法。
  • 您可以使用 ./ 来引用当前目录,但出于安全原因,您无法引用父目录,例如使用 ..
  • 如果指定目录,则该规则适用于目录中的所有文件和递归子目录。

实现 BackupAgent

实现自动备份的应用程序不需要实现 BackupAgent。 但是,您可以选择实现自定义的 BackupAgent。 通常,这样做有两个原因

  • 您希望收到备份事件的通知,例如 onRestoreFinished()onQuotaExceeded(long, long)。 即使应用程序未运行,也会执行这些回调方法。

  • 您无法使用 XML 规则轻松表达要备份的文件集。 在这些极少数情况下,您可以实现一个 BackupAgent,它会覆盖 onFullBackup(FullBackupDataOutput) 来存储您想要的内容。 要保留系统的默认实现,请使用 super.onFullBackup() 在超类上调用相应的方法。

如果实现了一个 BackupAgent,则系统默认情况下会期望您的应用程序执行 键值备份和恢复。 要改用基于文件的自动备份,请将 android:fullBackupOnly 属性设置为 true,位于您应用程序的清单中。

在自动备份和恢复操作期间,系统将在受限模式下启动应用程序,既可以防止应用程序访问可能导致冲突的文件,又可以使应用程序在 BackupAgent 中执行回调方法。 在这种受限模式下,应用程序的主活动不会自动启动,它的 内容提供者 不会初始化,并且会实例化基本类 Application,而不是应用程序的 清单 中声明的任何子类。

您的 BackupAgent 必须实现抽象方法 onBackup()onRestore(),它们用于键值备份。 如果您不想执行键值备份,可以将这些方法的实现留空。

有关更多信息,请参阅 扩展 BackupAgent