《Android应用开发攻略》——2.14 备份Android应用程序数据
2.14 備份Android應(yīng)用程序數(shù)據(jù)
Pratik Rupwal
2.14.1 問(wèn)題
當(dāng)用戶(hù)恢復(fù)出廠(chǎng)設(shè)置或者改用新的Android設(shè)備時(shí),應(yīng)用程序丟失存儲(chǔ)數(shù)據(jù)或者應(yīng)用程序設(shè)置。
2.14.2 解決方案
Android的Backup Manager(備份管理器)能夠在應(yīng)用程序重新安裝時(shí)自動(dòng)恢復(fù)備份數(shù)據(jù)或者應(yīng)用程序設(shè)置。
2.14.3 討論
Android的備份管理器本質(zhì)上以?xún)煞N模式運(yùn)行——備份和恢復(fù)。在備份操作期間,備份管理器(BackuManager類(lèi))詢(xún)問(wèn)應(yīng)用程序所要備份的數(shù)據(jù),并將其放入一個(gè)備份傳輸中,備份傳輸負(fù)責(zé)將數(shù)據(jù)發(fā)送到基于云的存儲(chǔ)中。在恢復(fù)操作期間,備份管理器從備份傳輸中讀取備份數(shù)據(jù),并將其返回給應(yīng)用程序,以便將數(shù)據(jù)恢復(fù)到設(shè)備上。應(yīng)用程序可以請(qǐng)求恢復(fù),但是在應(yīng)用程序安裝且與用戶(hù)關(guān)聯(lián)的備份數(shù)據(jù)存在時(shí),Android并不一定執(zhí)行恢復(fù)操作。恢復(fù)備份數(shù)據(jù)主要發(fā)生在用戶(hù)重置設(shè)備或者升級(jí)到新設(shè)備,并且重新安裝過(guò)去安裝的應(yīng)用程序時(shí)。
例2-19展示了為應(yīng)用程序?qū)崿F(xiàn)備份管理器以保存應(yīng)用程序當(dāng)前狀態(tài)的方法。
以下是這一過(guò)程各個(gè)步驟的簡(jiǎn)單描述:
1 . 在Eclipse中創(chuàng)建BackupManagerExample項(xiàng)目。
2 . 打開(kāi)layout/backup_restore.xml文件,并插入例2-19中的代碼。
3 . 打開(kāi)values/string.xml文件并插入例2-20中的代碼。
4 . 清單文件看上去將類(lèi)似于例2-21。
5 . 例2-22中的代碼完成了應(yīng)用程序備份管理器的實(shí)現(xiàn)。
例2-19:備份/恢復(fù)布局
例2-20:示例使用的字符串
<resources><string name="hello">Hello World, BackupManager!</string><string name="app_name">BackupManager</string><string name="filling_text">Choose Settings for your application:</string><string name="bacon_label">Sound On</string><string name="pastrami_label">Vibration On</string><string name="hummus_label">Backlight On</string><string name="extras_text">Extras:</string><string name="mayo_text">Use Orientation?</string><string name="tomato_text">Use Camera?</string> </resources>例2-21:AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.sym.backupmanager"android:versionCode="1"android:versionName="1.0"><uses-sdk android:minSdkVersion="9" /><application android:label="Backup/Restore" android:icon="@drawable/icon"android:backupAgent="ExampleAgent"> <!-- Here you specify the backup agent--><!--Some backup transports may require API keys or other metadata--><meta-data android:name="com.google.android.backup.api_key"android:value="INSERT YOUR API KEY HERE" /><activity android:name=".BackupManagerExample"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity> </application> </manifest>例2-22:備份/恢復(fù)活動(dòng)
package com.sym.backupmanager; import android.app.Activity; import android.app.backup.BackupManager; import android.os.Bundle; import android.util.Log; import android.widget.CheckBox; import android.widget.CompoundButton; import android.widget.RadioGroup; import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; public class BackupManagerExample extends Activity {static final String TAG = "BRActivity";static final Object[] sDataLock = new Object[0];static final String DATA_FILE_NAME = "saved_data";RadioGroup mFillingGroup;CheckBox mAddMayoCheckbox;CheckBox mAddTomatoCheckbox;File mDataFile;BackupManager mBackupManager;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.backup_restore);mFillingGroup = (RadioGroup) findViewById(R.id.filling_group);mAddMayoCheckbox = (CheckBox) findViewById(R.id.mayo);mAddTomatoCheckbox = (CheckBox) findViewById(R.id.tomato);mDataFile = new File(getFilesDir(), BackupManagerExample.DATA_FILE_NAME);mBackupManager = new BackupManager(this);populateUI();}void populateUI() {RandomAccessFile file;int whichFilling = R.id.pastrami;boolean addMayo = false;boolean addTomato = false;synchronized (BackupManagerExample.sDataLock) {boolean exists = mDataFile.exists();try {file = new RandomAccessFile(mDataFile, "rw");if (exists) {Log.v(TAG, "datafile exists");whichFilling = file.readInt();addMayo = file.readBoolean();addTomato = file.readBoolean();Log.v(TAG, " mayo=" + addMayo+ " tomato=" + addTomato+ " filling=" + whichFilling);} else {Log.v(TAG, "creating default datafile");writeDataToFileLocked(file,addMayo, addTomato, whichFilling);mBackupManager.dataChanged();}} catch (IOException ioe) {// 在這里進(jìn)行錯(cuò)誤處理!}}mFillingGroup.check(whichFilling);mAddMayoCheckbox.setChecked(addMayo);mAddTomatoCheckbox.setChecked(addTomato);mFillingGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {public void onCheckedChanged(RadioGroup group,int checkedId) {Log.v(TAG, "New radio item selected: " + checkedId);recordNewUIState();}});CompoundButton.OnCheckedChangeListener checkListener= new CompoundButton.OnCheckedChangeListener() {public void onCheckedChanged(CompoundButton buttonView,boolean isChecked) {Log.v(TAG, "Checkbox toggled: " + buttonView);recordNewUIState();}};mAddMayoCheckbox.setOnCheckedChangeListener(checkListener);mAddTomatoCheckbox.setOnCheckedChangeListener(checkListener);}void writeDataToFileLocked(RandomAccessFile file,boolean addMayo, boolean addTomato, int whichFilling)throws IOException {file.setLength(0L);file.writeInt(whichFilling);file.writeBoolean(addMayo);file.writeBoolean(addTomato);Log.v(TAG, "NEW STATE: mayo=" + addMayo+ " tomato=" + addTomato+ " filling=" + whichFilling);}void recordNewUIState() {boolean addMayo = mAddMayoCheckbox.isChecked();boolean addTomato = mAddTomatoCheckbox.isChecked();int whichFilling = mFillingGroup.getCheckedRadioButtonId();try {synchronized (BackupManagerExample.sDataLock) {RandomAccessFile file = new RandomAccessFile(mDataFile, "rw");writeDataToFileLocked(file, addMayo, addTomato, whichFilling);}} catch (IOException e) {Log.e(TAG, "Unable to record new UI state");}mBackupManager.dataChanged();} }數(shù)據(jù)備份不能保證在所有Android設(shè)備上可用。但是,如果設(shè)備沒(méi)有提供備份傳輸,應(yīng)用程序并不會(huì)受到不利影響。如果你相信用戶(hù)將從應(yīng)用程序的數(shù)據(jù)備份中獲益,就可以按照這個(gè)文檔中描述的步驟實(shí)現(xiàn)、測(cè)試這一功能,然后發(fā)布應(yīng)用程序,而不考慮設(shè)備是否實(shí)際執(zhí)行備份。當(dāng)應(yīng)用程序在不提供備份傳輸?shù)脑O(shè)備上運(yùn)行時(shí),它將正常運(yùn)作,但是不會(huì)接受來(lái)自備份管理器的回調(diào)來(lái)備份數(shù)據(jù)。
盡管你無(wú)法知道當(dāng)前傳輸手段是什么,但是始終可以確信,備份數(shù)據(jù)不會(huì)被設(shè)備上的其他應(yīng)用程序讀取。只有備份管理器和備份傳輸有權(quán)訪(fǎng)問(wèn)備份操作中所提供的數(shù)據(jù)。
警告: 因?yàn)樵拼鎯?chǔ)和傳輸服務(wù)在不同的設(shè)備上可能有差別,Android不能保證備份中的數(shù)據(jù)安全。在使用備份存儲(chǔ)敏感數(shù)據(jù)(如用戶(hù)名和密碼)時(shí),應(yīng)該始終保持警惕。
測(cè)試你的備份代理
實(shí)現(xiàn)備份代理之后,可以使用bmgr命令,按照如下步驟測(cè)試備份/恢復(fù)功能:
1 . 在合適的Android系統(tǒng)映像上安裝你的應(yīng)用程序。如果使用模擬器,創(chuàng)建和使用帶有Android 2.2(API Level 8)的AVD。如果使用真實(shí)設(shè)備,設(shè)備必須運(yùn)行Android 2.2或更高版本并內(nèi)建Android Market。
2 . 確保備份功能啟用。如果使用的是模擬器,可以從SDK tools/路徑用如下命令啟用備份功能:
adb shell bmgr enable true
如果使用的是設(shè)備,打開(kāi)系統(tǒng)設(shè)置,選擇Privacy(隱私),然后啟用“Back up my data” (備份我的數(shù)據(jù))和 “Automatic restore”(自動(dòng)恢復(fù))。
3 . 打開(kāi)應(yīng)用程序并初始化某些數(shù)據(jù)。
如果在你的應(yīng)用程序中已經(jīng)正常地實(shí)現(xiàn)了備份功能,在每次數(shù)據(jù)改變時(shí)將要求備份。例如,每當(dāng)用戶(hù)修改某些數(shù)據(jù),應(yīng)用程序?qū)?huì)調(diào)用dataChanged(),該方法在備份服務(wù)器隊(duì)列中添加一個(gè)備份請(qǐng)求,為了測(cè)試,你也可以用如下的bmgr命令發(fā)出一個(gè)請(qǐng)求:
adb shell bmgr backup your.package.name
4 . 初始化備份操作:
adb shell bmgr run
這條命令強(qiáng)制備份管理器執(zhí)行隊(duì)列中的所有備份請(qǐng)求。
5 . 卸載你的應(yīng)用程序:
adb uninstall your.package.name
6 . 重新安裝應(yīng)用程序。
如果備份代理成功,第4步中初始化的所有數(shù)據(jù)將被恢復(fù)。
總結(jié)
以上是生活随笔為你收集整理的《Android应用开发攻略》——2.14 备份Android应用程序数据的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: UE4_BIM替换材质处理流程
- 下一篇: Android:什么是签名、为什么要给应