码迷,mamicode.com
首页 > 移动开发 > 详细

Android API Guides---Data Backup

时间:2016-04-22 20:52:49      阅读:318      评论:0      收藏:0      [点我收藏+]

标签:

Android的备份服务让您能够将持久应用程序数据复制到远程“云”存储,以应用程序的数据和设置提供了一个还原点。如果用户执行出厂重置或转换到一个新的Andr??oid设备,重新安装应用程序时,系统自动恢复备份数据。通过这种方式,用户不需要再现其以前的数据或应用程序设置。这个过程是完全透明的用户,并且不会影响在应用程序中的功能或用户体验。
在备份操作(该应用程序可以请求),Android的备份管理器(备份管理器)查询您的备份数据的应用程序,然后将它交给一个备份传输,然后将数据传送到云存储。在还原操作过程中,备份管理器检索备份传输备份数据,并返回给应用程序,以便您的应用程序可以将数据恢复到设备。这有可能为你的应用程序中请求恢复,但不应该是必要的,Android的自动执行安装应用程序时还原操作,且存在与用户相关联的备份数据。在其中还原的备份数据的主要方案是,当一个用户重置其设备或升级到新的设备和它们的先前安装的应用程序被重新安装。
注意:备份服务是不适合与其他客户端同步应用程序数据或保存,你想正常的应用程序生命周期过程中访问数据。您无法读取或按需写入备份数据,并在不是通过备份管理器提供的API之外的任何方法不能访问它。
备份传输是Android的备份框架,它是由设备制造商和服务供应商可定制的客户端组件。备份传输可能会有所不同,从设备到设备和备份传输可在任何给定的设备是透明的,你的应用程序。备份管理器API隔离在一个给定的设备应用程序可从实际的备份传输您的应用程序通过一组固定的API与备份管理器进行通信,而不管底层传输的。
数据备份是不能保证是适用于所有的Andr??oid设备。然而,应用程序没有不利在一个设备不能提供一个备份传输的事件的影响。如果您认为用户将数据备份在应用程序中获益,那么作为本文件所述可以实现它,测试它,然后发布自己的应用程序,而哪些设备实际执行备份的任何问题。当你的应用程序不提供备份传输设备上运行,应用程序运行正常,但不会从备份管理器接收回调到备份数据。
虽然无法知道目前的交通是什么,你总是放心,您的备份数据无法通过设备上的其他应用程序读取。只有备份管理器备份传输访问您备份操作过程中提供的数据。
注意事项:由于云存储和运输服务可以从不同的设备到设备,Android可以约在使用备份数据的安全性没有保证。你应该总是谨慎地使用备份存储敏感数据,如用户名和密码。
基础
要备份的应用程序数据,您需要实现一个备份代理。您的备份代理是由备份管理器叫您提供所需备份的数据。它也被称为恢复备份数据重新安装应用程序时。备份管理器处理与云存储所有的数据交易(使用备份传输)和备份代理处理设备上的所有数据的事务。
要实现一个备份代理,你必须:
声明备份代理与android的清单文件:backupAgent属性。
注册一个备份服务应用程序。谷歌的Andr??oid提供备份服务对于大多数Android设备的备份服务,它要求你为了它的工作注册您的应用程序。其他任何可用的备份服务,也可能需要您为了存储在自己的服务器上的数据寄存器。
通过定义无论是备份代理:
扩展BackupAgent
该BackupAgent类提供与您的应用程序的备份管理器通信的核心接口。如果直接继承这个类,则必须覆盖onBackup()和OnRestore中()来处理备份和还原操作为您的数据。
要么
扩展BackupAgentHelper
该BackupAgentHelper类提供围绕BackupAgent类,它最大限度地降低代码,你需要编写量的方便包装。在你BackupAgentHelper,你必须使用一个或多个“帮手”的对象,它可以自动备份和恢复某些类型的数据,这样你就不需要实现onBackup()和OnRestore中()。
Android系统目前提供了从SharedPreferences和内部存储,将备份和恢复完整的文件的备份助手。
声明在您的清单中的备份代理
这是最简单的一步,所以一旦你的类名决定为你的备份代理,在你的清单与Android声明它:在 <application> 标记backupAgent属性。

例如:

<manifest ... >
    ...
    <application android:label="MyApplication"
                 android:backupAgent="MyBackupAgent">
        <activity ... >
            ...
        </activity>
    </application>
</manifest>
您可能需要使用另一个属性是安卓版本恢复。此属性需要一个布尔值,表明是否要比较生成备份数据的版本,无论恢复的当前应用程序版本的应用程序数据。 (默认值是“假”。)请参阅检查恢复数据版本以获取更多信息。
注意:备份服务和API,您必须使用仅适用于运行API等级8(Android 2.2的)或更高版本的设备,所以你也应该设置你的安卓的minSdkVersion属性设置为“8”。
注册为Android备份服务
谷歌提供使用Android的备份服务备份传输运行Android 2.2或更高大多数Android供电设备。
为了让您的应用程序使用Android备份服务执行备份,必须注册的服务您的应用程序接收备份服务键,然后申报Android清单备份服务的关键。
为了让您的备份服务键,注册为Android备份服务。当你注册,你将获得一个备份服务键和相应的<元数据> XML代码的Andr??oid清单文件,其中必须包括作为<application>元素的子项。例如:

<application android:label="MyApplication"
             android:backupAgent="MyBackupAgent">
    ...
    <meta-data android:name="com.google.android.backup.api_key"
        android:value="AEdPqrEAAAAIDaYEVgU6DJnyJdBmU7KLH3kszDXLv_4DIsEIyQ" />
</application>
Android的:名称必须是“com.google.android.backup.api_key”和android:值必须从Android备份服务登记收到的备份服务的关键。


如果您有多个应用程序,您必须注册各一台,使用相应的软件包名称。


注:Android的备份服务提供的备份传输不能保证适用于所有支持备份Android设备。有些设备可能支持备份使用不同的交通工具,有些设备可能不支持备份可言,也没有办法为你的应用程序知道运输设备上使用。不过,如果你的应用程序中实现备份,你应该始终具备Android备份服务备份服务键,以便在设备使用的Andr??oid备份服务运输您的应用程序可以执行备份。如果设备没有使用Android备份服务,然后与备份服务重点的<元数据>元素将被忽略。


扩展BackupAgent


大多数应用程序应该不需要直接扩展BackupAgent类,而应该延伸BackupAgentHelper采取自动备份和恢复文件的内置辅助类的优势。但是,您可能要扩展BackupAgent直接,如果你需要:


版本的数据格式。在恢复操作过程举例来说,如果你预计需要修改其中你写你的应用程序数据的格式,你可以建立一个备份代理交叉检查您的应用程序版本,如果设备上的版本进行任何必要的兼容性工作比所述备份数据的不同。有关详细信息,请参阅检查恢复数据版本。
相反,备份整个文件的,可以指定每个部分,以及如何然后还原到设备应备份数据的部分。 (这也可以帮助您管理不同的版本,因为你读取和写入数据的唯一实体,而不是完整的文件。)
备份数据库中的数据。如果您有要恢复当用户重新安装应用程序的SQLite数据库,你需要一个还原操作中建立一个自定义BackupAgent一个备份操作过程中读取相应的数据,然后创建表并插入数据。
如果您不需要执行任何上述任务,并希望从SharedPreferences或内部存储备份完整的文件,你应该跳到扩展BackupAgentHelper。


所需的方法


当你通过扩展BackupAgent创建一个备份代理,你必须实现以下回调方法:


onBackup()
备份管理器调用此方法,请求备份后。在这种方法中,您从设备读取应用程序数据,并通过你想备份到备份管理器中的数据,如在执行备份如下所述。
OnRestore中()
还原操作过程中的备份管理器调用此方法(你可以请求恢复,但系统自动执行恢复时,用户重新安装应用程序)。当调用此方法,备份管理器提供了备份数据,然后您再恢复到设备,如恢复执行如下所述。
执行备份


当它的时间来备份应用程序数据,备份管理器调用您的onBackup()方法。这是你必须提供应用程序数据的备份管理器,因此它可以被保存到云存储。


只有备份管理器可以调用备份代理的onBackup()方法。您的应用程序的数据变化,要执行备份的时候,你必须通过调用dataChanged()(请参见请求备份获取更多信息)请求的备份操作。备份请求不会导致您onBackup()方法的调用直接。相反,适当的时间备份管理器等待,然后执行对已请求进行备份,因为上次执行备份的所有应用程序的备份。


提示:在开发应用程序,你可以从与BMGR工具备份管理器立即启动备份操作。


当备份管理器调用你的onBackup()方法,它通过三个参数:


oldState
指向由应用程序提供的最后一次备份状态的开放,只读ParcelFileDescriptor。这是不是从云存储备份数据,但备份的最后一次onBackup数据的本地表示()被调用(由newState定义,下面,或者从OnRestore中() - 更多关于这个在下一节)。由于onBackup()不会让你在云存储读取现有的备份数据,你可以用这个地方的代表性,以确定您的数据是否自上次备份以来发生变化。
数据
一个BackupDataOutput对象,你用你的备份数据传送到备份管理器。
newState
一个开放的,读/写ParcelFileDescriptor指向中,你必须编写你交给数据(表示可以为您的文件的最后修改时间戳一样简单)的数据表示的文件。该对象下一次备份管理器调用你的onBackup()方法返回oldState。如果你不写你的备份数据newState,然后oldState将指向一个空文件在下一次备份管理器调用onBackup()。
使用这些参数,你应该实现你的onBackup()方法来做到以下几点:


检查是否您的数据已通过oldState比较当前数据自上次备份以来发生变化。如何你oldState读取数据要看你原来是写给newState(见第3步)。记录文件的状态,最简单的方法是其最后一次修改的时间戳。例如,这里是你如何能阅读和比较oldState时间戳:

// Get the oldState input stream
FileInputStream instream = new FileInputStream(oldState.getFileDescriptor());
DataInputStream in = new DataInputStream(instream);

try {
    // Get the last modified timestamp from the state file and data file
    long stateModified = in.readLong();
    long fileModified = mDataFile.lastModified();

    if (stateModified != fileModified) {
        // The file has been modified, so do a backup
        // Or the time on the device changed, so be safe and do a backup
    } else {
        // Don‘t back up because the file hasn‘t changed
        return;
    }
} catch (IOException e) {
    // Unable to read state file... be safe and do a backup
}
如果一切都没有改变,你不需要备份,跳到第3步。
如果你的数据发生了变化,相比oldState,写入当前数据的数据备份到云存储。
你必须写数据的每个块作为BackupDataOutput一个“实体”。实体是由唯一的密钥串确定一个扁平的二进制数据记录。因此,您备份数据集在概念上是设置键 - 值对。
一个实体添加到您的备份数据集,必须:
呼叫writeEntityHeader(),传递一个唯一的字符串键你要写的数据和数据大小。
呼叫writeEntityData(),传递包含您的数据一个字节的缓冲区的字节数从缓冲区中写入(这应该与传递给writeEntityHeader大小())。
例如,下面的代码变平某些数据转换成字节流,并将其写入到一个单一的实体

// Create buffer stream and data output stream for our data
ByteArrayOutputStream bufStream = new ByteArrayOutputStream();
DataOutputStream outWriter = new DataOutputStream(bufStream);
// Write structured data
outWriter.writeUTF(mPlayerName);
outWriter.writeInt(mPlayerScore);
// Send the data to the Backup Manager via the BackupDataOutput
byte[] buffer = bufStream.toByteArray();
int len = buffer.length;
data.writeEntityHeader(TOPSCORE_BACKUP_KEY, len);
data.writeEntityData(buffer, len);
对要备份的每一块数据执行此。您如何将您的数据转化为实体是由你(和你可能只使用一个实体)。
无论你是否执行备份(步骤2),写当前数据的newState ParcelFileDescriptor的表示。备份管理本地保持该对象作为当前备份的数据的表示。它它的备份要求下一次经过这回你作为oldState(),所以你可以决定其他备份是否是必要的(如在步骤1中处理)。如果没有当前的数据状态写入到该文件,然后oldState将是下一个回调过程中为空。
下面的示例保存当前数据到newState使用文件的最后修改时间戳记的表示:

FileOutputStream outstream = new FileOutputStream(newState.getFileDescriptor());
DataOutputStream out = new DataOutputStream(outstream);

long modified = mDataFile.lastModified();
out.writeLong(modified);

注意:如果您的应用程序数据保存到一个文件,请确保您使用同步的语句访问该文件,使您的备份代理程序无法读取该文件,同时在应用程序中的活动也被写入文件。
恢复执行
当它的时间来恢复您的应用程序数据,备份管理器调用备份代理的OnRestore中()方法。当调用此方法,备份管理器可将您的备份数据,以便您可以到设备上恢复它。
只有备份管理器可以调用OnRestore中(),它发生在系统自动安装应用程序,并认为现有的备份数据。但是,您可以通过调用requestRestore请求您的应用程序恢复操作()(请参阅请求恢复获取更多信息)。
注:在开发应用程序,您还可以请求恢复操作BMGR工具。
当备份管理器调用你的OnRestore中()方法,它通过三个参数:
数据
一个BackupDataInput,它允许你读你的备份数据。
应用程序版本号码
代表你的应用程序的Andr??oid值的整数:VERSIONCODE清单属性,因为它是当这些数据被备份。您可以使用此交叉检查当前的应用程序版本,并确定数据格式兼容。有关使用此处理不同的版本恢复数据的更多信息,请参见下面的章节关于检查恢复数据版本。
newState
一个开放的,读/写ParcelFileDescriptor指向在其中您必须编写得到了数据的最终备份状态的文件。这个对象在下一次onBackup()被调用返回oldState。回想一下,您还必须写同样的newState对象在onBackup()回调也表现在这里保证给onBackup()的oldState对象是有效的,即使第一次onBackup()恢复设备后调用。
在您的实现OnRestore中(),你应该叫上的数据readNextHeader()通过数据集中的所有实体进行迭代。对于找到的每个实体,执行以下操作:
获取与getKey实体键()。
比较实体键,你应该申报的BackupAgent类中静态最终字符串的已知键值的列表。当钥匙匹配你已知密钥字符串中的一个,进入一个语句来提取实体数据,并将其保存到设备:
获取与getDataSize(实体数据的大小),并创建一个大小的字节数组。
呼叫readEntityData(),并通过它的字节数组,这是数据会去,并指定起始偏移量和阅读的大小。
你的字节数组现在是满的,你可以读取数据并将其写入到你喜欢的设备。
在阅读和你的数据写回装置,写onBackup在你的数据到newState的状态参数为你做同样的()。

例如,这里是你如何能恢复由上一节的例子中备份的数据:

@Override
public void onRestore(BackupDataInput data, int appVersionCode,
                      ParcelFileDescriptor newState) throws IOException {
    // There should be only one entity, but the safest
    // way to consume it is using a while loop
    while (data.readNextHeader()) {
        String key = data.getKey();
        int dataSize = data.getDataSize();

        // If the key is ours (for saving top score). Note this key was used when
        // we wrote the backup entity header
        if (TOPSCORE_BACKUP_KEY.equals(key)) {
            // Create an input stream for the BackupDataInput
            byte[] dataBuf = new byte[dataSize];
            data.readEntityData(dataBuf, 0, dataSize);
            ByteArrayInputStream baStream = new ByteArrayInputStream(dataBuf);
            DataInputStream in = new DataInputStream(baStream);

            // Read the player name and score from the backup data
            mPlayerName = in.readUTF();
            mPlayerScore = in.readInt();

            // Record the score on the device (to a file or something)
            recordScore(mPlayerName, mPlayerScore);
        } else {
            // We don‘t know this entity key. Skip it. (Shouldn‘t happen.)
            data.skipEntityData();
        }
    }

    // Finally, write to the state blob (newState) that describes the restored data
    FileOutputStream outstream = new FileOutputStream(newState.getFileDescriptor());
    DataOutputStream out = new DataOutputStream(outstream);
    out.writeUTF(mPlayerName);
    out.writeInt(mPlayerScore);
}
在本实施例中,不使用传递给OnRestore中该应用版本号码参数()。但是,您可能想使用它,如果你选择执行当用户的应用程序的版本实际上已经向后移动备份(例如,用户从您的应用程序的版本1.5到1.0)。欲了解更多信息,请参阅有关检查恢复数据版本的部分。
举一个例子实施BackupAgent的,请参阅备份ExampleAgent类和恢复示例应用程序。
扩展BackupAgentHelper
你应该,如果你想备份整个文件(无论从SharedPreferences或内部存储)使用BackupAgentHelper建立你的备份代理。建立你与BackupAgentHelper备份代理需要的不仅仅是延长BackupAgent远远更少的代码,因为你没有实现onBackup()和OnRestore中()。
你的实现BackupAgentHelper必须使用一个或多个备份助手。备份助手是BackupAgentHelper传票来执行备份和还原操作为特定类型数据的专用组件。 Android框架目前提供了两种不同的助手:
SharedPreferencesBackupHelper备份SharedPreferences文件。
FileBackupHelper从内部存储备份文件。
您可以包括多个帮手在BackupAgentHelper,但需要为每个数据类型只有一个帮手。也就是说,如果你有多个SharedPreferences文件,那么你只需要一个SharedPreferencesBackupHelper。
对于要添加到您的BackupAgentHelper每个帮助,您必须在onCreate()方法中做到以下几点:
实例化所需的辅助类的实例。在类的构造函数时,必须指定要备份相应的文件(S)。
呼叫addHelper()给助手添加到您的BackupAgentHelper。
下面的部分描述了如何使用每个可用的助手的备份代理。
备份SharedPreferences
当你实例化一个SharedPreferencesBackupHelper,必须包括一个或多??个SharedPreferences文件的名称。
例如,要备份一个名为“user_preferences”一个SharedPreferences文件,使用BackupAgentHelper一个完整的备份代理是这样的:

public class MyPrefsBackupAgent extends BackupAgentHelper {
    // The name of the SharedPreferences file
    static final String PREFS = "user_preferences";

    // A key to uniquely identify the set of backup data
    static final String PREFS_BACKUP_KEY = "prefs";

    // Allocate a helper and add it to the backup agent
    @Override
    public void onCreate() {
        SharedPreferencesBackupHelper helper =
                new SharedPreferencesBackupHelper(this, PREFS);
        addHelper(PREFS_BACKUP_KEY, helper);
    }
}
这是您的整个备份代理。该SharedPreferencesBackupHelper包括所有的代码需要备份和恢复SharedPreferences文件。


当备份管理器调用onBackup()和OnRestore中(),BackupAgentHelper调用备份助手进行备份和恢复您指定的文件。


注:SharedPreferences是线程安全的,所以你可以安全地读取和写入共享的喜好,从您的备份代理等活动文件。


备份其他文件


当你实例化一个FileBackupHelper,你必须包括保存到你的应用程序的内部存储(如getFilesDir(),这是同一位置openFileOutput()写入文件中指定)一个或多个文件的名称。


例如,备份两个文件命名为“分数”和“统计”,使用BackupAgentHelper备份代理如下:

// Object for intrinsic lock
static final Object sDataLock = new Object();
然后创建与此锁synchronized语句每次读取或写入文件的时间。例如,这里是写在一场比赛中,以文件的最新比分同步语句:

try {
    synchronized (MyActivity.sDataLock) {
        File dataFile = new File(getFilesDir(), TOP_SCORES);
        RandomAccessFile raFile = new RandomAccessFile(dataFile, "rw");
        raFile.writeInt(score);
    }
} catch (IOException e) {
    Log.e(TAG, "Unable to write to file");
}
您应该同步到相同的锁你读的声明。
然后,在你BackupAgentHelper,必须重写onBackup()和OnRestore中()来备份使用相同的内部锁同步和恢复操作。例如,从上面的MyFile的BackupAgent例需要下列方法:

@Override
public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
          ParcelFileDescriptor newState) throws IOException {
    // Hold the lock while the FileBackupHelper performs backup
    synchronized (MyActivity.sDataLock) {
        super.onBackup(oldState, data, newState);
    }
}

@Override
public void onRestore(BackupDataInput data, int appVersionCode,
        ParcelFileDescriptor newState) throws IOException {
    // Hold the lock while the FileBackupHelper restores the file
    synchronized (MyActivity.sDataLock) {
        super.onRestore(data, appVersionCode, newState);
    }
}
。所有你需要做的就是添加你FileBackupHelper在onCreate()方法并重写onBackup()和OnRestore中()同步读取和写入操作。


举一个例子实施BackupAgentHelper与FileBackupHelper,请参阅备份FileHelperExampleAgent类和恢复示例应用程序。


检查恢复数据版本


当备份管理器将数据保存到云存储,它会自动包含您的应用程序的版本,你的manifest文件的Andr??oid定义:属性的versionCode。备份管理器调用来恢复你的数据备份代理之前,它着眼于安卓的versionCode所安装应用程序,并将其与记录在数据恢复设置的值。如果记录在恢复的数据集的版本比在设备上的应用程序的版本更新,则用户已降低了他们的应用程序。在这种情况下,备份管理器将中止还原操作您的应用程序,而不是打电话给你OnRestore中()方法,因为还原组被认为是毫无意义的旧版本。


您可以覆盖了Android此行为:restoreAnyVersion属性。此属性为“真”或“假”,以表明您是否希望不管还原集版本,以恢复应用程序。默认值是“假”。如果定义这是“真”,那么备份管理器将忽略安卓的versionCode并致电OnRestore中()方法在所有情况下。这样做,你可以手动检查你的OnRestore中()方法版本的差异,并采取必要做这些版本冲突的数据不兼容的任何步骤。


为了帮助您恢复操作过程中处理不同的版本,OnRestore中()方法传递您包含在恢复数据设置为appVersionCode参数的版本代码。然后,您可以用PackageInfo.versionCode现场查询当前应用程序的版本代码。例如:

PackageInfo info;
try {
    String name = getPackageName();
    info = getPackageManager().getPackageInfo(name,0);
} catch (NameNotFoundException nnfe) {
    info = null;
}

int version;
if (info != null) {
    version = info.versionCode;
}
然后简单比较来??自PackageInfo至()传递到OnRestore中的appVersionCode获得的版本。


注意:一定要了解你的Andr??oid设置的后果:为您的应用restoreAnyVersion为“true”。如果支持的备份应用程序的每个版本不正确地考虑OnRestore中期间在数据格式的变化(),然后在设备上的数据可以被保存在与当前安装的设备上的版本不兼容的格式。


请求备份


你可以通过调用dataChanged随时请求备份操作()。此方法通知备份管理器,你会用你的备份代理想备份您的数据。然后,备份管理器在未来适当的时机调用备份代理的onBackup()方法。通常情况下,你应该在每次数据的变化(当用户改变,你想备份的应用程序的偏好,如)请求备份。如果调用dataChanged()多次连续,备份管理器从代理请求备份之前,你的经纪人仍收到只需一个电话到onBackup()。


注:在开发应用程序,你可以要求一个备份,并与BMGR工具立即启动备份操作。


请求恢复


在您的应用程序的正常生活,你不应该需要申请恢复操作。他们的系统会自动检查备份数据,并执行安装应用程序时还原。但是,您可以手动调用requestRestore(),如果有必要请求恢复操作。在这种情况下,备份管理器调用你的OnRestore中()的实施,从目前的集备份数据的传递数据。


注:在开发应用程序,你可以要求与BMGR工具还原操作。


测试你的备份代理


一旦你实现你的备份代理,可以测试备份,并按照以下步骤恢复功能,使用BMGR。


一个合适的Andr??oid系统映像上安装应用程序
如果使用模拟器,创建并使用AVD采用Android 2.2(API等级8)。
如果使用的设备,该设备必须运行Android 2.2或更高版本,并已谷歌玩内置的。
确保备份已启用
如果使用模拟器,您可以启用从您的SDK工具/路径如下命令备份:

adb shell bmgr enable true
自动恢复。
打开应用程序并初始化一些数据
如果你已经在正确的应用程序中实现备份,那么它应该在每次请求备份数据的变化。例如,每个用户更改某些数据时,您的应用程序应该调用dataChanged(),这更增加了备份管理器队列备份请求。出于测试目的,你也可以用下面的命令BMGR一个请求:

adb shell bmgr backup your.package.name
启动备份操作:

adb shell bmgr run
这迫使备份管理器来执行其队列完全备份请求。
卸载应用程序:

adb uninstall your.package.name
重新安装应用程序。
如果你的备份代理是成功的,你在步骤4中初始化的数据被恢复。

Android API Guides---Data Backup

标签:

原文地址:http://blog.csdn.net/qq_21413973/article/details/51195275

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!