android备份服务流程

转自: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);
        }
    }

你可能感兴趣的:(android备份服务流程)