Android NDK开发详解用户数据和身份之通过自动备份功能备份用户数据

对于面向 Android 6.0(API 级别 23)或更高版本的系统并在相应系统中运行的应用,应用自动备份功能会自动备份应用内的用户数据。Android 通过将应用数据上传到用户的 Google 云端硬盘来保留这些数据;在 Google 云端硬盘中,这些数据受到用户的 Google 账号凭据的保护。在搭载 Android 9 或更高版本的设备上,系统会使用设备 PIN 码、解锁图案或密码对备份进行端到端加密。数据量上限是每位用户 25 MB。存储备份数据是免费的。应用可以自定义备份流程,也可以通过停用备份选择将其停用。

如需简要了解 Android 备份选项并获得有关应备份和恢复哪些数据的指南,请参阅数据备份概览。

备份的文件

默认情况下,自动备份功能会备份系统分配给应用的大多数目录中的文件:

共享的偏好设置文件

保存到应用的内部存储空间的文件,由 getFilesDir() 或 getDir(String, int) 访问

getDatabasePath(String) 返回的目录中的文件,其中还包含使用 SQLiteOpenHelper 类创建的文件

getExternalFilesDir(String) 返回的目录中的外部存储空间中的文件

自动备份会排除 getCacheDir()、getCodeCacheDir() 和 getNoBackupFilesDir() 返回的目录中的文件。在这些位置保存的文件只是临时需要,备份操作会特意排除这些文件。

您可以将应用配置为包含和排除特定文件。如需了解详情,请参阅包含和排除文件部分。
注意:Android 不会将组件配置视为用户数据。如果应用在运行时启用或停用其清单中的特定组件,自动备份不会自动保存和恢复相应配置。如需保留配置状态,请将状态信息存储在共享偏好设置中,并在恢复时恢复共享偏好设置。

备份位置

备份数据存储在用户的 Google 云端硬盘账号的私人文件夹中,每个应用的数据量上限为 25 MB。保存的数据不计入用户的个人 Google 云端硬盘配额。系统仅存储最新备份。进行备份时,之前的所有备份都会被删除。用户或设备上的其他应用无法读取备份数据。

用户可以查看已备份到 Google 云端硬盘 Android 应用中的应用列表。在 Android 设备中,用户可以在 Google 云端硬盘应用的抽屉式导航栏中找到此列表,方法是依次转到设置 > 备份和重置。

每个设备设置生命周期中的备份存储在不同的数据集内,具体如以下示例所述:

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

如果用户将设备恢复出厂设置,然后使用相同的账号设置此设备,备份会存储在新的数据集内。过时数据集会在一段闲置时间后自动删除。

注意:如果数据量超过 25 MB,系统就会调用 onQuotaExceeded(),并且不会将数据备份到云端。之后,系统会定期检查数据量是否回落到 25 MB 的阈值以下,并在低于此阈值时继续进行自动备份。

备份计划

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

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

在实践中,这些情况大概每天晚上都会发生,但设备可能永远不会进行备份(例如,如果设备一直未连接到网络)。为了节省网络带宽,仅在应用数据发生更改时才会进行上传。

在自动备份期间,系统会关闭应用以确保其不再向文件系统写入数据。默认情况下,备份系统会忽略在前台运行的应用,以避免用户体验不佳。您可以通过将 android:backupInForeground 属性设为 true 来替换默认行为。

为了简化测试,Android 提供了可以手动启动应用备份的工具。如需了解详情,请参阅测试备份和恢复。

恢复计划

每当通过 Play 商店安装应用、在设备设置过程中安装应用(系统安装曾经安装的应用时)或通过运行 adb 安装应用时,系统都会恢复数据。恢复操作会在 APK 安装完成后且应用可供用户启动前的这段时间内发生。

在初始设备设置向导运行期间,系统会向用户显示可用的备份数据集列表,并询问用户从哪个数据集恢复数据。选择哪个备份数据集,哪个数据集就会成为设备的原始数据集。设备可以从自己的备份或原始数据集进行恢复。如果这两个来源的备份都可用,设备会优先考虑自己的备份。如果用户未完成设备设置向导,设备只能从自己的备份进行恢复。

为了简化测试,Android 提供了可以手动启动应用恢复的工具。如需了解详情,请参阅测试备份和恢复。

启用和停用备份

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

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

您可以通过将 android:allowBackup 设为 false 来停用备份。如果应用可以通过其他机制重新创建其状态,或者应用会处理敏感信息,则可能需要执行此操作。
注意:对于在 Android 12(API 级别 31)或更高版本上运行且以其为目标平台的应用,指定 android:allowBackup=“false” 会停止备份到 Google 云端硬盘,但不会停止应用的设备间传输。如需了解详情,请参阅备份和恢复方面的变更的相关信息。

包含和排除文件

默认情况下,系统会备份几乎所有应用数据。如需了解详情,请参阅备份的文件部分。

本部分介绍了如何定义自定义 XML 规则以控制备份的内容。如果您的应用以 Android 12(API 级别 31)或更高版本为目标平台,您必须指定一组额外的 XML 备份规则(如本部分中所述),以支持在搭载这些 Android 版本的设备上引入的备份恢复更改。

在 Android 11 及更低版本中控制备份

如需控制在搭载 Android 11(API 级别 30)或更低版本的设备上备份的文件,请按照本部分中的步骤操作。
重要提示:如果应用是以 Android 11 或更低版本为目标平台,这些 XML 备份规则也会用于搭载 Android 12 或更高版本的设备。请参阅下一部分,了解一组额外的 XML 备份规则,以支持在搭载 Android 12 或更高版本的设备上引入的备份恢复更改。

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

">
</application>

在 res/xml/ 目录中创建名为 @xml/backup_rules 的 XML 文件。在此文件中,使用 和 元素添加规则。以下示例会备份除 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)或更高版本中,您可以添加以下条件:

clientSideEncryption:用户的备份使用客户端密钥加密。只要用户在 Android 9 或更高版本中启用了备份功能,并为设备设置了屏幕锁定(PIN 码、图案或密码),这种加密形式就会在搭载 Android 9 或更高版本的设备中启用。
deviceToDeviceTransfer:用户正在将其备份转移到支持本地设备到设备转移的其他设备(例如,Google Pixel)。

如果您已将开发设备升级到 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>

注意:由于向 XML 添加要求会阻止备份在之前的 Android 版本中运行,请针对在搭载 Android 8.1(API 级别 27)或更低版本的设备上使用的备份提供备用资源。

如果您的应用实现了键值对备份系统,或您自己实现了 BackupAgent,您还可将这些条件要求应用于您的备份逻辑,方法是在 BackupDataOutput 对象的传输标记集与自定义备份代理的 FLAG_CLIENT_SIDE_ENCRYPTION_ENABLED 或 FLAG_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 或更高版本的设备上备份哪些文件。
重要提示:即使您的应用是以 Android 12 或更高版本为目标平台,您也必须另外指定一组 XML 备份规则,以支持搭载 Android 11(API 级别 30)或更低版本的设备。

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

.xml">
</application>

在 res/xml/ 目录中创建名为 backup_rules.xml 的 XML 文件。在此文件中,使用 和 元素添加规则。以下示例会备份除 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"] path="string"
    requireFlags=["clientSideEncryption" | "deviceToDeviceTransfer"] />
    <exclude domain=["file" | "database" | "sharedpref" | "external" |
                     "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"] path="string"/>
    ...
    <exclude domain=["file" | "database" | "sharedpref" | "external" |
                        "root"] path="string"/>
    ...
  </cloud-backup>
  <device-transfer>
    ...
    <include domain=["file" | "database" | "sharedpref" | "external" |
                        "root"] path="string"/>
    ...
    <exclude domain=["file" | "database" | "sharedpref" | "external" |
                        "root"] path="string"/>
    ...
  </device-transfer>
</data-extraction-rules>

配置的每一部分( 和 )包含仅适用于该传输类型的规则。例如,这种分离可让您从 Google 云端硬盘备份中排除某个文件或目录,同时仍在设备到设备 (D2D) 传输过程中传输该文件或目录。如果您的文件因太大而无法备份到云端,但可在设备之间顺利传输,上述做法会很有用。

如果您没有为某种特定的备份模式指定规则(例如,如果缺少 部分),则系统会为除 no-backup 和 cache 目录之外的所有内容完全启用该模式,如备份的文件部分中所述。

您的应用可以在 部分中设置 disableIfNoEncryptionCapabilities 标志,以确保只有在可以加密时(例如,当用户具有锁定屏幕时)备份操作才会发生。如果用户的设备无法支持加密,设置此约束条件可阻止将备份内容发送到云端,但由于不会将 D2D 传输内容发送到服务器,因此即使在不支持加密的设备上,D2D 传输也会继续执行。
用于包含和排除元素的语法

在 、 和 标记(具体取决于设备的 Android 版本和应用的 targetSDKVersion)内,您可以定义 和 元素:

用于指定要备份的文件或文件夹。默认情况下,自动备份会涵盖应用的几乎所有文件。如果您指定 <include> 元素,系统在默认情况下不会再包含任何文件,而仅备份指定的文件。如需包含多个文件,请使用多个 <include> 元素。

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

系统始终会排除 getCacheDir()、getCodeCacheDir() 或 getNoBackupFilesDir() 所返回目录中的文件,即使您尝试包含这些文件也是如此。
提示:如需备份用户凭据和身份验证令牌,请不要将其存储在共享偏好设置或文件中,而是改用 Block Store API 来存储和管理凭据。这有助于确保它们能被安全存储并能与其他应用数据一起备份和恢复。
指定在备份期间要排除的文件或文件夹。以下是通常会从备份中排除的一些文件:

    包含由服务器发出或在设备上生成的设备特定标识符的文件。例如,每当用户在新设备上安装您的应用时,Firebase Cloud Messaging (FCM) 都需要生成注册令牌。如果旧的注册令牌恢复了,应用可能会出现意外行为。

    与应用调试相关的文件。

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

注意:如果您的配置文件同时指定了这两个元素,备份会包含 <include> 元素指定的所有资源,同时减去 <exclude> 元素指定的资源。换句话说,<exclude> 优先级较高。

每个 和 元素都必须包含以下两个属性:

domain

用于指定资源的位置。此属性的有效值包括以下各项:

    root - 文件系统上的目录,会存储属于此应用的所有不公开文件。
    file - getFilesDir() 返回的目录。
    database - getDatabasePath() 返回的目录。 使用 SQLiteOpenHelper 创建的数据库存储在此处。
    sharedpref - 存储 SharedPreferences 的目录。
    external - getExternalFilesDir() 返回的目录。

注意:您无法在这些位置之外备份文件。

path

用于指定备份要包含或排除的文件或文件夹。请注意以下几点:

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

实现 BackupAgent

实现了自动备份的应用不需要实现 BackupAgent。不过,您可以根据需要实现自定义 BackupAgent。通常,这样做有两个原因:

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

您无法使用 XML 规则轻松地表达要备份的文件集。在这样的极少数情况下,您可以实现一个用于替换 onFullBackup(FullBackupDataOutput) 的 BackupAgent 来存储您想要的内容。如需保留系统的默认实现,请使用 super.onFullBackup() 对父类调用相应的方法。

如果您实现了 BackupAgent,在默认情况下,系统会要求您的应用执行键值对备份和恢复操作。如需改用基于文件的自动备份功能,请在应用清单中将 android:fullBackupOnly 属性设置为 true。

在自动备份和恢复操作执行过程中,系统会以受限模式启动应用,以防止应用访问可能导致冲突的文件,并让应用能够在其 BackupAgent 中执行回调方法。在此受限模式下,应用的主 activity 不会自动启动,其 content provider 不会初始化,并且基类 Application(而不是应用的清单中声明的任何子类)会实例化。
注意:为了避免错误,请确保在受限模式下执行的应用部分(主要是 BackupAgent)不会访问同一应用中的 content provider,或试图转换 Application 对象的类型。如果无法避免这些模式,请考虑实现键值对备份或彻底停用备份。

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

如需了解详情,请参阅扩展 BackupAgent。

本页面上的内容和代码示例受内容许可部分所述许可的限制。Java 和 OpenJDK 是 Oracle 和/或其关联公司的注册商标。

最后更新时间 (UTC):2023-11-07。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

五一编程

程序之路有我与你同行

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值