原文
快速查看
·
·
·
·
在本文中
关键类
参阅
为了给应用程序的数据和配置信息提供数据还原点,Android的备份backup服务允许把需持久保存的数据拷贝到远程“云”存储中。如果用户恢复了出厂设置或者换用新的Android设备,系统将在再次安装应用程序时自动恢复备份数据。这样,就不需要用户复制之前的数据和程序配置信息。整个过程对于用户而言完全透明,不会影响程序的功能和用户体验度。
在备份过程中(应用程序可发起请求),Android的备份管理器(BackupManager)将查找应用程序中需备份的数据,并把数据交给备份传输器,传输器再把数据传送给云存储。在恢复时,备份管理器从备份传输器取回备份数据并将其返回给应用程序,然后应用程序就能把数据恢复到设备上。应用程序也能够发起恢复请求,但不是必须的——如果程序安装完毕且存在用户相关的备份数据,Android会自动执行恢复操作。恢复备份数据主要发生于以下场合:用户重置设备或者升级到新设备后,以前装过的应用程序又被再次安装。
注意:备份服务并不是为以下用途设计的:与其它客户端同步、在程序正常生命周期内保存数据。备份数据不允许随意读写,除通过备份管理器提供的API外无法访问数据。
备份传输器是Android备份框架的客户端组件,它可由设备制造商和提供商定制。备份传输器可以因设备不同而不同,对于应用程序而言它是透明的。备份管理器的API将应用程序和实际备份传输器联接起来——程序通过一组固定的API与备份管理器进行通讯,而不必关心底层的传输过程。
并不是所有Android平台的设备都能支持数据备份。不过,即使设备不支持备份传输,对程序运行也不会有什么影响。如果确信用户将受益于数据备份服务,只管按照本文所述去实现、测试并发布即可,而不必去关心哪些设备会真正执行备份工作。就算是在不支持备份传输的设备上,程序仍然会正常运行,只是不能接收备份管理器的请求进行数据备份而已。
尽管对当前所传输内容一无所知,但尽管放心,备份数据是不能被设备上的其它程序读取的。在备份过程中,只有备份管理器和备份传输器有权限访问被提交的数据。
警告:因为云存储和传输服务依设备而各不相同,Android不保证使用备份服务数据的安全性。如果要利用备份服务保存敏感数据(比如用户名和密码),应该始终保持谨慎态度。
为了备份应用程序数据,需要实现一个备份代理。此备份代理将被备份管理器调用,用于提供所需备份的数据。当程序重装时,还要调用此代理来恢复数据。备份管理器处理所有与云存储之间的数据传输工作(利用备份传输器),备份代理则负责所有对设备上数据的处理。
要实现备份代理,必须:
1.
2.
3.
BackupAgent
BackupAgentHelper
Android目前提供两种backuphelper,用于从SharedPreferences
在Manifest中声明备份代理
这是最容易的一步,一旦确定了类名,就可在manifest的<application>
例如:
<manifest
</manifest>
其它可能会用到的属性是android:restoreAnyVersion。这个属性用布尔值标明恢复数据时是否忽略当前程序和产生备份数据的程序之间的版本差异(默认值是“false”)。详情请参阅检查恢复数据的版本。
注意:备份服务和API只在运行APILevel 8(Android2.2)以上版本的设备上才可用,因此应把android:minSdkVersion
为Android备份服务进行注册
Google为大多数Android2.2以上版本的设备提供了利用Android备份服务进行的备份传输服务。
为了程序能利用Android备份服务执行备份操作,必须对程序进行注册以获得一个BackupService Key,然后在Androidmanifest文件中声明这个Key。
要获取BackupService Key,请为Android服务进行注册。注册时会得到一个BackupService Key和Androidmanifest文件内相应的<meta-data>
<application
</application>
android:name
如果存在多个应用程序,必须根据各自的程序包名称(packagename)为每一个程序进行注册。
注意:即使设备能够支持,Android备份服务提供的备份传输器也不一定在所有Android
继承BackupAgent
大多数应用程序应该不需要直接继承使用BackupAgent
·
·
·
如果不需要执行以上的任务,而只是从SharedPreferences或内部存储备份完整的文件,请跳转到继承BackupAgentHelper。
通过继承BackupAgent创建备份代理时,必须实现以下回调方法:
备份管理器在程序请求备份后将调用本方法。如下文执行备份所述,在本方法中实现从设备读取应用程序数据,并把需备份的数据传递给备份管理器。
备份管理器在恢复数据时调用本方法(也可以主动请求恢复,但在用户重装应用程序时系统会自动执行数据恢复。)如下文执行恢复所述,备份管理器调用本方法时将传入备份的数据,然后就可把数据恢复到设备上。
执行备份
备份应用程序数据时,备份管理器将调用onBackup()
只有备份管理器能够调用备份代理中的onBackup()方法。每当数据发生改变并需要执行备份时,必须调用dataChanged()发起一次备份请求(详情请参阅请求备份)。备份请求并不会立即导致onBackup()方法的调用。备份服务器会等待合适的时机,为上次备份操作后又发出备份请求的所有应用程序执行备份。
提示:在开发应用程序的过程中,可以用bmgr工具让备份管理器立即执行备份操作。
当备份管理器调用onBackup()方法时,传入以下三个参数:
oldState
已打开的、只读的文件描述符ParcelFileDescriptor,指向应用程序提供的有关上次备份数据状态的文件。这不是来自云存储的备份数据,而是记录上次调用onBackup()所备份数据相关状态信息的本地文件(如下文newState所定义,或来自下节onRestore())。因为onBackup()不允许读取保存于云存储的数据,可以根据此信息来判断数据自上次备份以来是否变动过。
data
BackupDataOutput对象,用于将备份数据传给备份管理器。
newState
已打开的、可读写的文件描述符ParcelFileDescriptor,指向一个文件,必须将提交给data参数的数据相关状态信息写入此文件(此状态信息可以简单到只是文件的最后修改时间戳)。备份管理器下次调用onBackup()时,本对象作为oldState传入。如果没有往newState写入信息,则备份管理器下次调用onBackup()时oldState
利用以上参数,可以实现onBackup()方法如下:
1.
//
FileInputStream
DataInputStream
try
}
// Unable to read state file... be safe and do abackup
}
如果数据没有发生变化,就不需要进行备份,请跳转到第3步。
2.
必须以BackupDataOutput中的“entity”方式写入每一块数据。一个entity是用一个唯一字符串键值标识的拼接二进制数据记录。因此,所备份的数据集其实上是一组键值对。
要在备份数据集中增加一个entity,必须:
1.
2.
例如,以下代码把一些数据拼接为字节流并写入一个entity:
//
ByteArrayOutputStream
DataOutputStream
//
outWriter.writeUTF(mPlayerName);
outWriter.writeInt(mPlayerScore);
//
byte[]
int
data.writeEntityHeader(TOPSCORE_BACKUP_KEY,
data.writeEntityData(buffer,
对每一块需备份的数据都要执行以上操作。程序负责把数据切分为多个entity(当然也可以只用一个entity)。
3.
以下例子把文件最后修改时间戳作为当前数据的状态存入newState:
FileOutputStream outstream = newFileOutputStream(newState.getFileDescriptor());
DataOutputStream out = newDataOutputStream(outstream);
long modified =mDataFile.lastModified();
out.writeLong(modified);
警告:如果应用程序数据存放于文件中,请确保使用同步语句(synchronized)来访问文件。这样在应用程序的Activity写文件时,备份代理就不会去读文件了。