編寫:kesenhoo - 原文:http://developer.android.com/training/cloudsync/backupapi.html
當(dāng)用戶購買了一臺新的設(shè)備或者是對當(dāng)前的設(shè)備做了恢復(fù)出廠設(shè)置的操作,用戶會希望在進(jìn)行初始化設(shè)置的時(shí)候,Google Play 能夠把之前安裝過的應(yīng)用恢復(fù)到設(shè)備上。默認(rèn)情況是,用戶的這些期望并不會發(fā)生,他們之前的設(shè)置與數(shù)據(jù)都會丟失。
對于一些數(shù)據(jù)量相對較少的情況(通常少于1MB),例如用戶偏好設(shè)置、筆記、游戲分?jǐn)?shù)或者是其他的一些狀態(tài)數(shù)據(jù),可以使用 Backup API 來提供一個(gè)輕量級的解決方案。這節(jié)課會介紹如何將 Backup API 集成到我們的應(yīng)用當(dāng)中,以及如何利用 Backup API 將數(shù)據(jù)恢復(fù)到新的設(shè)備上。
這節(jié)課中所使用的 Android Backup Service 需要進(jìn)行注冊。我們可以點(diǎn)擊這里進(jìn)行注冊。注冊成功后,服務(wù)器會提供一段類似于下面的代碼,我們需要將它添加到應(yīng)用的 Manifest 文件中:
<meta-data android:name="com.google.android.backup.api_key"
android:value="ABcDe1FGHij2KlmN3oPQRs4TUvW5xYZ" />
請注意,每一個(gè)備份 Key 都只能在特定的包名下工作。如果我們有不同的應(yīng)用需要使用這個(gè)方法進(jìn)行備份,那么需要分別為他們進(jìn)行注冊。
使用 Android 的備份服務(wù)需要將兩個(gè)額外的內(nèi)容添加到應(yīng)用的 Manifest 文件中。首先,聲明備份代理的類名,然后添加一段類似上面的代碼作為 Application 標(biāo)簽的子標(biāo)簽。假設(shè)我們的備份代理叫作 TheBackupAgent,下面的例子展示了如何在 Manifest 文件中添加這些信息:
<application android:label="MyApp"
android:backupAgent="TheBackupAgent">
...
<meta-data android:name="com.google.android.backup.api_key"
android:value="ABcDe1FGHij2KlmN3oPQRs4TUvW5xYZ" />
...
</application>
創(chuàng)建備份代理最簡單的方法是繼承 BackupAgentHelper。 創(chuàng)建這個(gè)幫助類實(shí)際上非常簡便。首先創(chuàng)建一個(gè)類,其類名和上述 Manifest 文件中聲明的類名一致(本例中,它叫做 TheBackupAgent),然后繼承 BackupAgentHelper,之后重寫 onCreate() 方法。
在 onCreate() 中創(chuàng)建一個(gè) BackupHelper。這些幫助類是專門用來備份某些數(shù)據(jù)的。目前 Android Framework 包含了兩種幫助類:FileBackupHelper 與 SharedPreferencesBackupHelper。在我們創(chuàng)建一個(gè)幫助類并且指向需要備份的數(shù)據(jù)的時(shí)候,僅僅需要使用 addHelper() 方法將它們添加到 BackupAgentHelper 當(dāng)中, 之后再增加一個(gè) Key 用來恢復(fù)數(shù)據(jù)。大多數(shù)情況下,完整的實(shí)現(xiàn)差不多只需要10行左右的代碼。
下面是一個(gè)對高分?jǐn)?shù)據(jù)進(jìn)行備份的例子:
import android.app.backup.BackupAgentHelper;
import android.app.backup.FileBackupHelper;
public class TheBackupAgent extends BackupAgentHelper {
// The name of the SharedPreferences file
static final String HIGH_SCORES_FILENAME = "scores";
// 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
@Override
void onCreate() {
FileBackupHelper helper = new FileBackupHelper(this, HIGH_SCORES_FILENAME);
addHelper(FILES_BACKUP_KEY, helper);
}
}
為了使得程序更加靈活,FileBackupHelper 的構(gòu)造函數(shù)可以帶有任意數(shù)量的文件名。我們只需簡單地通過增加一個(gè)額外的參數(shù),就能實(shí)現(xiàn)同時(shí)對最高分文件與游戲進(jìn)度文件進(jìn)行備份,如下所述:
@Override
void onCreate() {
FileBackupHelper helper = new FileBackupHelper(this, HIGH_SCORES_FILENAME, PROGRESS_FILENAME);
addHelper(FILES_BACKUP_KEY, helper);
}
備份用戶偏好同樣比較簡單。和創(chuàng)建 FileBackupHelper 一樣來創(chuàng)建一個(gè) SharedPreferencesBackupHelper。在這種情況下, 不是添加文件名到構(gòu)造函數(shù)當(dāng)中,而是添加被應(yīng)用所使用的 Shared Preference Groups 的名稱。下面的例子展示的是,如果高分?jǐn)?shù)據(jù)是以 Preference 的形式而非文件的形式存儲的,備份代理幫助類應(yīng)該如何設(shè)計(jì):
import android.app.backup.BackupAgentHelper;
import android.app.backup.SharedPreferencesBackupHelper;
public class TheBackupAgent extends BackupAgentHelper {
// The names of the SharedPreferences groups that the application maintains. These
// are the same strings that are passed to getSharedPreferences(String, int).
static final String PREFS_DISPLAY = "displayprefs";
static final String PREFS_SCORES = "highscores";
// An arbitrary string used within the BackupAgentHelper implementation to
// identify the SharedPreferencesBackupHelper's data.
static final String MY_PREFS_BACKUP_KEY = "myprefs";
// Simply allocate a helper and install it
void onCreate() {
SharedPreferencesBackupHelper helper =
new SharedPreferencesBackupHelper(this, PREFS_DISPLAY, PREFS_SCORES);
addHelper(MY_PREFS_BACKUP_KEY, helper);
}
}
雖然我們可以根據(jù)喜好增加任意數(shù)量的備份幫助類到備份代理幫助類中,但是請記住每一種類型的備份幫助類只需要一個(gè)就夠了。一個(gè) FileBackupHelper 可以處理所有我們想要備份的文件, 而一個(gè) SharedPreferencesBackupHelper 則能夠處理所有我們想要備份的 Shared Preference Groups。
為了請求一個(gè)備份,僅僅需要創(chuàng)建一個(gè) BackupManager 實(shí)例,然后調(diào)用它的 dataChanged() 方法即可:
import android.app.backup.BackupManager;
...
public void requestBackup() {
BackupManager bm = new BackupManager(this);
bm.dataChanged();
}
該調(diào)用會告知備份管理器即將有數(shù)據(jù)會被備份到云端。在之后的某個(gè)時(shí)間點(diǎn),備份管理器會執(zhí)行備份代理的 onBackup() 方法。無論任何時(shí)候,只要數(shù)據(jù)發(fā)生了改變,我們都可以去調(diào)用它,并且不用擔(dān)心這樣會增加網(wǎng)絡(luò)的負(fù)荷。如果我們在備份正式發(fā)生之前請求了兩次備份,那么最終備份操作僅僅會出現(xiàn)一次。
一般而言,我們不應(yīng)該手動去請求恢復(fù),而是應(yīng)該讓應(yīng)用安裝到設(shè)備上的時(shí)候自動進(jìn)行恢復(fù)。然而,如果確實(shí)有必要手動去觸發(fā)恢復(fù),只需要調(diào)用 requestRestore() 方法就可以了。