转自:http://bbs.hikemobile.com/thread-318-1-1.html
android
备份服务允许你把应用程序数据放到云端存储,如果用户把手机恢复出厂设置或者重新安装了应用程序,
系统会自动恢复应用程序之前的数据。
1.在manifest file里面添加android:backupAgent属性
2.向backup service注册你的application
3.定义backup agent
注册服务
,
这里的
value
是
android backup service key.
<application android:label="MyApplication"
android:backupAgent="MyBackupAgent">
<meta-data android:name="com.google.android.backup.api_key"
android:value="AEdPqrEAAAAIDaYEVgU6DJnyJdBmU7KLH3kszDXLv_4DIsEIyQ" />
</application>
继承BackupAgentHelper,目前android提供两种helper,
SharedPreferencesBackupHelper 备份 SharedPreferences 文件
FileBackupHelper 从内部存储设备中备份文件.
备份名为user_preferences的 SharedPreferences
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);
}
}
备份
scores
和
stats
文件
public class
MyFileBackupAgent
extends
BackupAgentHelper {
// The name of the SharedPreferences file
static final
String TOP_SCORES = "scores";
static final
String PLAYER_STATS = "stats";
// A key to uniquely identify the set of backup data
static final
String FILES_BACKUP_KEY = "myfiles";
// Allocate a helper and add it to the backup agent
void
onCreate() {
FileBackupHelper helper = new FileBackupHelper(this, TOP_SCORES, PLAYER_STATS);
addHelper(FILES_BACKUP_KEY, helper);
}
}
注意:在读写文件的时候不是线程安全的,所以我们需要用锁来保证数据的一致性
static final Object sDataLock = new Object();
因此,上面的类需要加入以下函数
@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);
}
}
测试你的
backup agent
1.在系统设置里面打开你的备份
2.adb shell bmgr backup your.package.name
3.adb shell bmgr run
4.adb uninstall your.package.name
5.Re-install your application
根据上面的部分代码写一个测试是能够成功运行并看到效果的。
根据
MyPrefsBackupAgent
这个例子来理一下程序的流程
当上面
adb shell bmgr run
开始执行的时候会发起备份请求使系统进入
BackupServiceBinder
的
doBackup
函数执行(
BackupAgent.java
)
其中调用到
BackupAgent.this.onBackup()
;该函数是一个虚函数,因此会执行到它的子类
BackupAgentHelper.
BackupHelperDispatcher mDispatcher = new BackupHelperDispatcher();
mDispatcher.performBackup();
再来看看
BackupHelperDispatcher
中
doOneBackup(oldState, data, newState, header, helper);
helper.performBackup(oldState, data, newState);
这里的
helper
是什么?
MyPrefsBackupAgent onCreate
里面有个
addHelper()
函数,该函数将
helper
加入到
mDispatcher
mDispatcher.addHelper(keyPrefix, helper);
所以这个helper就是SharedPreferencesBackupHelper
回到前面的performBackup
helper.performBackup其实就是调用了SharedPreferencesBackupHelper里面的performBackup
在这里可以看到
public void performBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
ParcelFileDescriptor newState) {
.............................
for (int i=0; i<N; i++) {
files = context.getSharedPrefsFile(prefGroups).getAbsolutePath();
}
performBackup_checked(oldState, data, newState, files, prefGroups);
}
performBackup_checked会涉及到jni的调用,最终会通过BackupHelpers.cpp的back_up_files函数来实现备份.
dataStream->WriteEntityHeader
dataStream->WriteEntityData
一个entity是用一个唯一字符串键值标识的拼接二进制数据记录,备份的数据集其实上是一组键值对
对每一块需备份的数据都要执行以上操作。程序负责把数据切分为多个entity
恢复的流程和
backup
的流程一样,
SharedPreferencesBackupHelper.java
的
restoreEntity
函数
public void restoreEntity(BackupDataInputStream data) {
Context context = mContext;
String key = data.getKey();
if (DEBUG) Log.d(TAG, "got entity '" + key + "' size=" + data.size());
if (isKeyInList(key, mPrefGroups)) {
File f = context.getSharedPrefsFile(key).getAbsoluteFile();
writeFile(f, data);
}
}