《Android應用開發攻略》——2.14 備份Android應用程序數據

2.14 備份Android應用程序數據

Pratik Rupwal
2.14.1 問題
當用戶恢復出廠設置或者改用新的Android設備時,應用程序丟失存儲數據或者應用程序設置。
2.14.2 解決方案
Android的Backup Manager(備份管理器)能夠在應用程序重新安裝時自動恢復備份數據或者應用程序設置。
2.14.3 討論
Android的備份管理器本質上以兩種模式運行——備份和恢復。在備份操作期間,備份管理器(BackuManager類)詢問應用程序所要備份的數據,并將其放入一個備份傳輸中,備份傳輸負責將數據發送到基于云的存儲中。在恢復操作期間,備份管理器從備份傳輸中讀取備份數據,并將其返回給應用程序,以便將數據恢復到設備上。應用程序可以請求恢復,但是在應用程序安裝且與用戶關聯的備份數據存在時,Android并不一定執行恢復操作。恢復備份數據主要發生在用戶重置設備或者升級到新設備,并且重新安裝過去安裝的應用程序時。
例2-19展示了為應用程序實現備份管理器以保存應用程序當前狀態的方法。
以下是這一過程各個步驟的簡單描述:
1 . 在Eclipse中創建BackupManagerExample項目。
2 . 打開layout/backup_restore.xml文件,并插入例2-19中的代碼。
3 . 打開values/string.xml文件并插入例2-20中的代碼。
4 . 清單文件看上去將類似于例2-21。
5 . 例2-22中的代碼完成了應用程序備份管理器的實現。
例2-19:備份/恢復布局

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical"android:layout_width="match_parent"android:layout_height="wrap_content"><ScrollViewandroid:orientation="vertical"android:layout_width="fill_parent"android:layout_height="fill_parent"android:layout_weight="1"><LinearLayoutandroid:orientation="vertical"android:layout_width="match_parent"android:layout_height="wrap_content"><TextView android:text="@string/filling_text"android:textSize="20dp"android:layout_marginTop="20dp"android:layout_marginBottom="10dp"android:layout_width="match_parent"android:layout_height="wrap_content"/><RadioGroup android:id="@+id/filling_group"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginLeft="20dp"android:orientation="vertical"><RadioButton android:id="@+id/bacon"android:text="@string/bacon_label"/><RadioButton android:id="@+id/pastrami"android:text="@string/pastrami_label"/><RadioButton android:id="@+id/hummus"android:text="@string/hummus_label"/></RadioGroup><TextView android:text="@string/extras_text"android:textSize="20dp"android:layout_marginTop="20dp"android:layout_marginBottom="10dp"android:layout_width="match_parent"android:layout_height="wrap_content"/><CheckBox android:id="@+id/mayo"android:text="@string/mayo_text"android:layout_marginLeft="20dp"android:layout_width="match_parent"android:layout_height="wrap_content"/><CheckBox android:id="@+id/tomato"android:text="@string/tomato_text"android:layout_marginLeft="20dp"android:layout_width="match_parent"android:layout_height="wrap_content"/></LinearLayout></ScrollView>
</LinearLayout>

例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:備份/恢復活動

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) {// 在這里進行錯誤處理!}}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();}
}

數據備份不能保證在所有Android設備上可用。但是,如果設備沒有提供備份傳輸,應用程序并不會受到不利影響。如果你相信用戶將從應用程序的數據備份中獲益,就可以按照這個文檔中描述的步驟實現、測試這一功能,然后發布應用程序,而不考慮設備是否實際執行備份。當應用程序在不提供備份傳輸的設備上運行時,它將正常運作,但是不會接受來自備份管理器的回調來備份數據。
盡管你無法知道當前傳輸手段是什么,但是始終可以確信,備份數據不會被設備上的其他應用程序讀取。只有備份管理器和備份傳輸有權訪問備份操作中所提供的數據。
警告: 因為云存儲和傳輸服務在不同的設備上可能有差別,Android不能保證備份中的數據安全。在使用備份存儲敏感數據(如用戶名和密碼)時,應該始終保持警惕。
測試你的備份代理
實現備份代理之后,可以使用bmgr命令,按照如下步驟測試備份/恢復功能:
1 . 在合適的Android系統映像上安裝你的應用程序。如果使用模擬器,創建和使用帶有Android 2.2(API Level 8)的AVD。如果使用真實設備,設備必須運行Android 2.2或更高版本并內建Android Market。
2 . 確保備份功能啟用。如果使用的是模擬器,可以從SDK tools/路徑用如下命令啟用備份功能:
adb shell bmgr enable true
如果使用的是設備,打開系統設置,選擇Privacy(隱私),然后啟用“Back up my data” (備份我的數據)和 “Automatic restore”(自動恢復)。
3 . 打開應用程序并初始化某些數據。
如果在你的應用程序中已經正常地實現了備份功能,在每次數據改變時將要求備份。例如,每當用戶修改某些數據,應用程序將會調用dataChanged(),該方法在備份服務器隊列中添加一個備份請求,為了測試,你也可以用如下的bmgr命令發出一個請求:
adb shell bmgr backup your.package.name
4 . 初始化備份操作:
adb shell bmgr run
這條命令強制備份管理器執行隊列中的所有備份請求。
5 . 卸載你的應用程序:
adb uninstall your.package.name
6 . 重新安裝應用程序。
如果備份代理成功,第4步中初始化的所有數據將被恢復。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/281041.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/281041.shtml
英文地址,請注明出處:http://en.pswp.cn/news/281041.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

C#程序開機啟動與獲取程序啟動路徑

寫windows工具時&#xff0c;要進行電源管理&#xff0c;需要重啟與開關機OS&#xff0c;這樣工具就需要自動啟動。查了網上很多資料&#xff0c;修改注冊列表就可以。 但是&#xff0c;復制幾個網站的代碼并自己修改都發現不行&#xff0c;最后發現腳本之家這段代碼才成功&am…

wpf office 菜單_如何帶回Office 2007中的舊菜單

wpf office 菜單Using the new Ribbon feature in Office 2007 takes time to learn…time you don’t have because projects are stacking up. Today we will look at UBitMenu, a utility that puts the familiar Office 2003 menu into the 2007 ribbon. 使用Office 2007中…

Swagger UI 僅為用戶暴露已授權終結點

前言當需要在生產環境中提供 Swagger UI 時&#xff0c;我們可以通過身份驗證&#xff0c;控制只有授權用戶才能訪問 Swagger UI 頁面。但是我們希望更進一步&#xff0c;每個用戶只能看到授權給他的終結點&#xff0c;而不會暴露其他未授權終結點信息。比如&#xff0c; API 提…

php實現約瑟夫環

function king($high,$size){ $monkey range(1, $high); $i 0 ; while (count($monkey)>1) { $i; $head array_shift($monkey); if(($i % $size) ! 0){ array_push($monkey,$head); } } return $monkey[0];} var_dump(king(10,3));轉載于:https://www.cnblogs.com/lijint…

微軟正式發布Azure Storage上的靜態網站

微軟正式宣布了Azure Storage上的靜態網站&#xff0c;提供了從托管在Azure Storage上的HTML、CSS和JavaScript文件提供內容的能力。靜態網站包含內容固定的Web頁面&#xff0c;同時仍然允許利用JavaScript等客戶端代碼來創建豐富的用戶體驗。 有了這個新功能&#xff0c;繼用于…

帝國國王科技大學上機題解(二)

1.找到字符串中出現次數最少的字符 題目描寫敘述 給定一個字符串&#xff08;長度小于50&#xff09; 找到該字符串出現次數最少的字符 假設有兩個字符出現次數同樣&#xff0c;并且均出現最少。那么ASCII碼小的字符優先 輸入 輸入為一行字符串。不含空格 輸出 輸出出現次數最少…

如何在計算機上閱讀漫畫書

Reading and organizing a comic book collection on your computer is efficient and a lot of fun. Today we will look at a couple of free applications that allow you to read your favorite comic books on your computer. 在計算機上閱讀和組織漫畫集非常有效&#xf…

C# WinForm 自啟動/模擬開機自動啟動

遇到重寫啟動步驟&#xff0c;C#調試時顯得比較折騰&#xff0c;既要等待重啟&#xff0c;又要保存當前文件。 讓程序自動重啟模擬這樣電腦重啟步驟&#xff0c;顯得非常方便。在http://bbs.csdn.net/topics/100187453找到下面代碼&#xff0c;直接使用。 ProcessStartInfo p…

工業互聯網平臺實現路徑

我國工業互聯網平臺建設雖然仍處于產業培育期&#xff0c;但是工業互聯網平臺也得到了初期的快速發展&#xff0c;得益于平臺企業的積極投入和各地工業和信息化主管部門的大力推動&#xff0c;從平臺建設推廣的經驗來看&#xff0c;下面談一下個人認為傳統制造企業平臺戰略比較…

Javascript基礎之-Promise

轉載自: http://www.lht.ren/article/3/ Promise是什么呢&#xff1f;根據ecma-262的定義&#xff1a; Promise是一個被用于延時計算的最終結果的占位符 &#xff08;A Promise is an object that is used as a placeholder for the eventual results of a deferred (and possi…

linux進階命令2

linux進階命令2 壓縮1.壓縮的概念1&#xff09;壓縮的目的&#xff1a; 在網絡傳遞文件時&#xff0c;可以先將文件壓縮&#xff0c;然后傳遞壓縮后的文件&#xff0c;從而減少網絡帶寬。 接受者接受文件后&#xff0c;解壓即可。2&#xff09;壓縮的類型 有損壓縮、無損壓縮。…

PHP經常使用正則表達式匯總

1. 平時做站點常常要用正則表達式&#xff0c;以下是一些解說和樣例&#xff0c;僅供大家參考和改動使用&#xff1a; 2. "^\d$"  //非負整數&#xff08;正整數 0&#xff09; 3. "^[0-9]*[1-9][0-9]*$"  //正整數 4. "^((-\d)|…

psa name_Windows 10安全性PSA:啟用自動商店更新

psa nameMicrosoft sometimes distributes important security updates through the Microsoft Store. That’s the lesson we’re learning in July 2020, when Microsoft sent an important update for Windows 10’s HEVC codecs not via Windows Update but via the Store.…

C# ListView 簡單命令例子

編寫工具常用到ListView控件&#xff0c;能簡單列出選項&#xff0c;常用到流程校驗顯示。這里介紹簡答顯示&#xff0c;添加與刪除功能。 1.添加表頭&#xff0c;與顯示。 this.listView1.Columns.Add("隊列", 40, HorizontalAlignment.Left);this.listView1.Column…

C#并行編程-Task

什么是異步同步和異步主要用于修飾方法。當一個方法被調用時&#xff0c;調用者需要等待該方法執行完畢并返回才能繼續執行&#xff0c;我們稱這個方法是同步方法&#xff1b;當一個方法被調用時立即返回&#xff0c;并獲取一個線程執行該方法內部的業務&#xff0c;調用者不用…

手機照片丟失或誤刪如何恢復

手機照片丟失或誤刪如何恢復&#xff1f;我們每個人從剛出生就開始拍照片&#xff0c;一周歲照片、二周歲照片、三周歲照片等&#xff0c;因為照片可以記錄我們從小到大的模樣和變化。無意照片對我們每個人來說都很重要&#xff0c;如果手機突然壞以前的照片都找不到了怎么辦呢…

C++學習筆記(二)——交換函數(swap)

這次我們要透過一個簡單的函數swap深入理解函數傳參的本質以及在C中如何選擇傳參方式。 先來看第一段程序&#xff1a; void swap(int x, int y) {int temp y;y x;x temp; } 通過main函數的調用&#xff0c;我們發現x,y并未實現交換&#xff1a; int main() {int x 1;int y…

大數據背后是個萬億市場

2014年的GDP中消費占比已經超過了50%&#xff0c;標志著中國經濟正在向市場經濟轉型&#xff0c;消費占GDP50%&#xff0d;70%是中等發達國家向市場經濟過渡的一個表現&#xff0c;未來中國經濟增長最大的引擎應該來源于消費&#xff0c;特別是個人消費。中國正在經歷經濟結構調…

ipad iphone開發_如何將iPhone或iPad置于恢復模式

ipad iphone開發If your iDevice starts acting strangely and you’ve run through the gamut of normal troubleshooting fixes, Recovery Mode may be your answer. This lets you easily reset the device and re-install iOS using iTunes. 如果您的iDevice開始運行異常&a…

從三層架構說起,談談對歷史項目的小改造

web development項目背景說明最近接手一個 “老” 項目的需求修改&#xff0c;項目整體基于 .net core 3.1 平臺&#xff0c;以傳統的三層架構為基礎構建。了解需求后&#xff0c;逐步對原有項目框架進行大概的了解&#xff0c;主要是熟悉一些框架的開發規范&#xff0c;基本工…