Android-Data Backup

》 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:

  1. Get the entity key with getKey().
  2. 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:
    1. Get the entity data size with getDataSize() and create a byte array of that size.
    2. Call readEntityData() and pass it the byte array, which is where the data will go, and specify the start offset and the size to read.
    3. Your byte array is now full and you can read the data and write it to the device however you like.
  3. 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() andonRestore().

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:

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 oneSharedPreferencesBackupHelper.

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

  1. Instantiate in instance of the desired helper class. In the class constructor, you must specify the appropriate file(s) you want to backup.
  2. 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 moreSharedPreferences files.

For example, to back up a SharedPreferences file named "user_preferences", a complete backup agent usingBackupAgentHelper 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(getFilesDir(), TOP_SCORES);
        RandomAccessFile raFile = new RandomAccessFile(dataFile, "rw");
        raFile.writeInt(score);
    }
} catch (IOException e) {
    Log.e(TAG, "Unable to write to file");
}

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);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值