您的位置:首页 > 移动开发 > Android开发

Android-Data Backup

2015-12-23 22:27 507 查看
》 Android's
backup
service
allows you to copy your persistent application data to remote "cloud" storage, in order to provide a restore point for the application data and settings.

During a backup operation (which your application can request), Android's Backup Manager (
BackupManager
)
queries your application for backup data, then hands it to a backup transport, which then delivers the data to the cloud storage.

Data backup is not guaranteed
to be available on all Android-powered devices.

Caution: Because
the cloud storage and transport service can differ from device to device, Android makes no guarantees about the security of your data while using backup. You should always be cautious about using backup to store sensitive data, such as usernames and passwords.

》This
is the easiest step, so once you've decided on the class name for your backup agent, declare it in your manifest with the
android:backupAgent
attribute
in the
<application>
tag.

For example:
<manifest ... >
...
<application android:label="MyApplication"
android:backupAgent="MyBackupAgent">
<activity ... >
...
</activity>
</application>
</manifest>

》To get
your Backup Service Key, register for Android Backup Service.
When you register, you will be provided a Backup Service Key and the appropriate
<meta-data>
XML code for your Android manifest file, which you must
include as a child of the
<application>
element. For example:

<application android:label="MyApplication"
android:backupAgent="MyBackupAgent">
...
<meta-data android:name="com.google.android.backup.api_key"
android:value="AEdPqrEAAAAIDaYEVgU6DJnyJdBmU7KLH3kszDXLv_4DIsEIyQ" />
</application>


The
android:name
must be
"com.google.android.backup.api_key"
and the
android:value
must be the Backup Service Key received from the Android Backup Service registration.
When you create a backup
agent by extending
BackupAgent
,
you must implement the following callback methods:onBackup()onRestore()

》Check whether your data has changed since the last backup by comparing
oldState
to
your current data. How you read data in
oldState
depends on how you originally wrote it to
newState
(see
step 3). The easiest way to record the state of a file is with its last-modified timestamp. For example, here's how you can read and compare a timestamp from
oldState
:

// Get the oldState input stream
FileInputStream instream = new FileInputStream(oldState.getFileDescriptor());
DataInputStream in = new DataInputStream(instream);

try {
// Get the last modified timestamp from the state file and data file
long stateModified = in.readLong();
long fileModified = mDataFile.lastModified();

if (stateModified != fileModified) {
// The file has been modified, so do a backup
// Or the time on the device changed, so be safe and do a backup
} else {
// Don't back up because the file hasn't changed
return;
}
} catch (IOException e) {
// Unable to read state file... be safe and do a backup
}


If
your data has changed, compared to
oldState
, write the current data to
data
to
back it up to the cloud storage.

// Create buffer stream and data output stream for our data
ByteArrayOutputStream bufStream = new ByteArrayOutputStream();
DataOutputStream outWriter = new DataOutputStream(bufStream);
// Write structured data
outWriter.writeUTF(mPlayerName);
outWriter.writeInt(mPlayerScore);
// Send the data to the Backup Manager via the BackupDataOutput
byte[] buffer = bufStream.toByteArray();
int len = buffer.length;
data.writeEntityHeader(TOPSCORE_BACKUP_KEY, len);
data.writeEntityData(buffer, len);

Whether or not you perform a backup (in step 2), write a representation of the current data to the
newState
ParcelFileDescriptor
.
The Backup Manager retains this object locally as a representation of the data that is currently backed up.

FileOutputStream outstream = new FileOutputStream(newState.getFileDescriptor());
DataOutputStream out = new DataOutputStream(outstream);

long modified = mDataFile.lastModified();
out.writeLong(modified);

Caution: If your application data is saved to a file, make sure that you use synchronized statements
while accessing the file so that your backup agent does not read the file while an Activity in your application is also writing the file.

In your implementation of
onRestore()
,
you should call
readNextHeader()
on the
data
to
iterate through all entities in the data set. For each entity found, do the following:

Get the entity key with
getKey()
.
Compare the entity key to a list of known key values that you should have declared as static final strings inside your
BackupAgent
class.
When the key matches one of your known key strings, enter into a statement to extract the entity data and save it to the device:

Get the entity data size with
getDataSize()
and
create a byte array of that size.
Call
, int, int)]readEntityData()
and
pass it the byte array, which is where the data will go, and specify the start offset and the size to read.
Your byte array is now full and you can read the data and write it to the device however you like.

After you read and write your data back to the device, write the state of your data to the
newState
parameter the same as you do during
onBackup()
.

For example, here's how you can restore the data backed up by the example in the previous section:
@Override
public void onRestore(BackupDataInput data, int appVersionCode,
ParcelFileDescriptor newState) throws IOException {
// There should be only one entity, but the safest
// way to consume it is using a while loop
while (data.readNextHeader()) {
String key = data.getKey();
int dataSize = data.getDataSize();

// If the key is ours (for saving top score). Note this key was used when
// we wrote the backup entity header
if (TOPSCORE_BACKUP_KEY.equals(key)) {
// Create an input stream for the BackupDataInput
byte[] dataBuf = new byte[dataSize];
data.readEntityData(dataBuf, 0, dataSize);
ByteArrayInputStream baStream = new ByteArrayInputStream(dataBuf);
DataInputStream in = new DataInputStream(baStream);

// Read the player name and score from the backup data
mPlayerName = in.readUTF();
mPlayerScore = in.readInt();

// Record the score on the device (to a file or something)
recordScore(mPlayerName, mPlayerScore);
} else {
// We don't know this entity key. Skip it. (Shouldn't happen.)
data.skipEntityData();
}
}

// Finally, write to the state blob (newState) that describes the restored data
FileOutputStream outstream = new FileOutputStream(newState.getFileDescriptor());
DataOutputStream out = new DataOutputStream(outstream);
out.writeUTF(mPlayerName);
out.writeInt(mPlayerScore);
}

》 Extending BackupAgentHelper

You should build your backup agent using
BackupAgentHelper
if you want to
back up complete files (from either
SharedPreferences
or internal
storage). Building your backup agent with
BackupAgentHelper
requires
far less code than extending
BackupAgent
, because you don't have to implement
onBackup()
and
onRestore()
.

Your implementation of
BackupAgentHelper
must use one or more backup helpers.
A backup helper is a specialized component that
BackupAgentHelper
summons
to perform backup and restore operations for a particular type of data. The Android framework currently provides two different helpers:

SharedPreferencesBackupHelper
to
backup
SharedPreferences
files.
FileBackupHelper
to backup files from internal
storage.

You can include multiple helpers in your
BackupAgentHelper
, but only one
helper is needed for each data type. That is, if you have multiple
SharedPreferences
files,
then you need only one
SharedPreferencesBackupHelper
.

For each helper you want to add to your
BackupAgentHelper
, you must do the
following during your
onCreate()
method:

Instantiate in instance of the desired helper class. In the class constructor, you must specify the appropriate file(s) you want to backup.
Call
addHelper()
to
add the helper to your
BackupAgentHelper
.

The following sections describe how to create a backup agent using each of the available helpers.


Backing up SharedPreferences

When you instantiate a
SharedPreferencesBackupHelper
, you must
include the name of one or more
SharedPreferences
files.

For example, to back up a
SharedPreferences
file named "user_preferences", a
complete backup agent using
BackupAgentHelper
looks like this:
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);
}
}

public class MyFileBackupAgent extends BackupAgentHelper {
// The name of the 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
@Override
public void onCreate() {
FileBackupHelper helper = new FileBackupHelper(this,
TOP_SCORES, PLAYER_STATS);
addHelper(FILES_BACKUP_KEY, helper);
}
}


here's a synchronized statement for writing the latest score in a game to a file:
try {
synchronized (MyActivity.sDataLock) {
File dataFile = new File([code]getFilesDir()
, TOP_SCORES);
RandomAccessFile raFile = new RandomAccessFile(dataFile, "rw");
raFile.writeInt(score);
}
} catch (IOException e) {
Log.e(TAG, "Unable to write to file");
}[/code]

Then, in your
BackupAgentHelper
, you must override
onBackup()
and
onRestore()
to
synchronize the backup and restore operations with the same intrinsic lock. For example, the
MyFileBackupAgent
example from above needs the following methods:
@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);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: