11c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate/* 21c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate * Copyright (C) 2010 The Android Open Source Project 31c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate * 41c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate * Licensed under the Apache License, Version 2.0 (the "License"); 51c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate * you may not use this file except in compliance with the License. 61c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate * You may obtain a copy of the License at 71c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate * 81c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate * http://www.apache.org/licenses/LICENSE-2.0 91c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate * 101c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate * Unless required by applicable law or agreed to in writing, software 111c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate * distributed under the License is distributed on an "AS IS" BASIS, 121c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 131c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate * See the License for the specific language governing permissions and 141c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate * limitations under the License. 151c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate */ 161c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate 171c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tatepackage com.example.android.backuprestore; 181c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate 191c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tateimport android.app.backup.BackupAgent; 201c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tateimport android.app.backup.BackupDataInput; 211c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tateimport android.app.backup.BackupDataOutput; 221c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tateimport android.os.ParcelFileDescriptor; 231c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate 241c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tateimport java.io.ByteArrayInputStream; 251c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tateimport java.io.ByteArrayOutputStream; 261c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tateimport java.io.DataInputStream; 271c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tateimport java.io.DataOutputStream; 281c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tateimport java.io.File; 291c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tateimport java.io.FileInputStream; 301c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tateimport java.io.FileOutputStream; 311c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tateimport java.io.IOException; 321c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tateimport java.io.RandomAccessFile; 331c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate 341c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate/** 351c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate * This is the backup/restore agent class for the BackupRestore sample 361c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate * application. This particular agent illustrates using the backup and 371c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate * restore APIs directly, without taking advantage of any helper classes. 381c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate */ 391c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tatepublic class ExampleAgent extends BackupAgent { 401c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate /** 411c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate * We put a simple version number into the state files so that we can 421c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate * tell properly how to read "old" versions if at some point we want 431c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate * to change what data we back up and how we store the state blob. 441c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate */ 451c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate static final int AGENT_VERSION = 1; 461c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate 471c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate /** 481c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate * Pick an arbitrary string to use as the "key" under which the 491c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate * data is backed up. This key identifies different data records 501c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate * within this one application's data set. Since we only maintain 511c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate * one piece of data we don't need to distinguish, so we just pick 521c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate * some arbitrary tag to use. 531c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate */ 541c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate static final String APP_DATA_KEY = "alldata"; 551c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate 561c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate /** The app's current data, read from the live disk file */ 571c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate boolean mAddMayo; 581c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate boolean mAddTomato; 591c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate int mFilling; 601c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate 611c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate /** The location of the application's persistent data file */ 621c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate File mDataFile; 631c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate 641c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate /** For convenience, we set up the File object for the app's data on creation */ 651c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate @Override 661c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate public void onCreate() { 671c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate mDataFile = new File(getFilesDir(), BackupRestoreActivity.DATA_FILE_NAME); 681c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate } 691c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate 701c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate /** 711c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate * The set of data backed up by this application is very small: just 721c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate * two booleans and an integer. With such a simple dataset, it's 731c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate * easiest to simply store a copy of the backed-up data as the state 741c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate * blob describing the last dataset backed up. The state file 751c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate * contents can be anything; it is private to the agent class, and 761c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate * is never stored off-device. 771c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate * 781c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate * <p>One thing that an application may wish to do is tag the state 791c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate * blob contents with a version number. This is so that if the 801c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate * application is upgraded, the next time it attempts to do a backup, 811c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate * it can detect that the last backup operation was performed by an 821c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate * older version of the agent, and might therefore require different 831c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate * handling. 841c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate */ 851c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate @Override 861c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data, 871c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate ParcelFileDescriptor newState) throws IOException { 881c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate // First, get the current data from the application's file. This 891c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate // may throw an IOException, but in that case something has gone 901c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate // badly wrong with the app's data on disk, and we do not want 911c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate // to back up garbage data. If we just let the exception go, the 921c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate // Backup Manager will handle it and simply skip the current 931c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate // backup operation. 941c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate synchronized (BackupRestoreActivity.sDataLock) { 951c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate RandomAccessFile file = new RandomAccessFile(mDataFile, "r"); 961c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate mFilling = file.readInt(); 971c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate mAddMayo = file.readBoolean(); 981c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate mAddTomato = file.readBoolean(); 991c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate } 1001c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate 1011c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate // If the new state file descriptor is null, this is the first time 1021c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate // a backup is being performed, so we know we have to write the 1031c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate // data. If there <em>is</em> a previous state blob, we want to 1041c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate // double check whether the current data is actually different from 1051c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate // our last backup, so that we can avoid transmitting redundant 1061c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate // data to the storage backend. 1071c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate boolean doBackup = (oldState == null); 1081c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate if (!doBackup) { 1091c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate doBackup = compareStateFile(oldState); 1101c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate } 1111c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate 1121c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate // If we decided that we do in fact need to write our dataset, go 1131c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate // ahead and do that. The way this agent backs up the data is to 1141c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate // flatten it into a single buffer, then write that to the backup 1151c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate // transport under the single key string. 1161c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate if (doBackup) { 1171c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate ByteArrayOutputStream bufStream = new ByteArrayOutputStream(); 1181c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate 1191c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate // We use a DataOutputStream to write structured data into 1201c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate // the buffering stream 1211c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate DataOutputStream outWriter = new DataOutputStream(bufStream); 1221c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate outWriter.writeInt(mFilling); 1231c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate outWriter.writeBoolean(mAddMayo); 1241c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate outWriter.writeBoolean(mAddTomato); 1251c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate 1261c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate // Okay, we've flattened the data for transmission. Pull it 1271c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate // out of the buffering stream object and send it off. 1281c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate byte[] buffer = bufStream.toByteArray(); 1291c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate int len = buffer.length; 1301c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate data.writeEntityHeader(APP_DATA_KEY, len); 1311c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate data.writeEntityData(buffer, len); 1321c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate } 1331c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate 1341c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate // Finally, in all cases, we need to write the new state blob 1351c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate writeStateFile(newState); 1361c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate } 1371c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate 1381c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate /** 1391c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate * Helper routine - read a previous state file and decide whether to 1401c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate * perform a backup based on its contents. 1411c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate * 1421c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate * @return <code>true</code> if the application's data has changed since 1431c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate * the last backup operation; <code>false</code> otherwise. 1441c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate */ 1451c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate boolean compareStateFile(ParcelFileDescriptor oldState) { 1461c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate FileInputStream instream = new FileInputStream(oldState.getFileDescriptor()); 1471c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate DataInputStream in = new DataInputStream(instream); 1481c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate 1491c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate try { 1501c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate int stateVersion = in.readInt(); 1511c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate if (stateVersion > AGENT_VERSION) { 1521c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate // Whoops; the last version of the app that backed up 1531c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate // data on this device was <em>newer</em> than the current 1541c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate // version -- the user has downgraded. That's problematic. 1551c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate // In this implementation, we recover by simply rewriting 1561c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate // the backup. 1571c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate return true; 1581c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate } 1591c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate 1601c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate // The state data we store is just a mirror of the app's data; 1611c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate // read it from the state file then return 'true' if any of 1621c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate // it differs from the current data. 1631c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate int lastFilling = in.readInt(); 1641c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate boolean lastMayo = in.readBoolean(); 1651c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate boolean lastTomato = in.readBoolean(); 1661c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate 1671c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate return (lastFilling != mFilling) 1681c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate || (lastTomato != mAddTomato) 1691c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate || (lastMayo != mAddMayo); 1701c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate } catch (IOException e) { 1711c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate // If something went wrong reading the state file, be safe 1721c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate // and back up the data again. 1731c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate return true; 1741c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate } 1751c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate } 1761c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate 1771c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate /** 1781c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate * Write out the new state file: the version number, followed by the 1791c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate * three bits of data as we sent them off to the backup transport. 1801c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate */ 1811c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate void writeStateFile(ParcelFileDescriptor stateFile) throws IOException { 1821c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate FileOutputStream outstream = new FileOutputStream(stateFile.getFileDescriptor()); 1831c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate DataOutputStream out = new DataOutputStream(outstream); 1841c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate 1851c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate out.writeInt(AGENT_VERSION); 1861c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate out.writeInt(mFilling); 1871c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate out.writeBoolean(mAddMayo); 1881c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate out.writeBoolean(mAddTomato); 1891c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate } 1901c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate 1911c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate /** 1921c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate * This application does not do any "live" restores of its own data, 1931c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate * so the only time a restore will happen is when the application is 1941c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate * installed. This means that the activity itself is not going to 1951c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate * be running while we change its data out from under it. That, in 1961c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate * turn, means that there is no need to send out any sort of notification 1971c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate * of the new data: we only need to read the data from the stream 1981c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate * provided here, build the application's new data file, and then 1991c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate * write our new backup state blob that will be consulted at the next 2001c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate * backup operation. 2011c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate * 2021c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate * <p>We don't bother checking the versionCode of the app who originated 2031c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate * the data because we have never revised the backup data format. If 2041c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate * we had, the 'appVersionCode' parameter would tell us how we should 2051c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate * interpret the data we're about to read. 2061c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate */ 2071c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate @Override 2081c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate public void onRestore(BackupDataInput data, int appVersionCode, 2091c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate ParcelFileDescriptor newState) throws IOException { 2101c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate // We should only see one entity in the data stream, but the safest 2111c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate // way to consume it is using a while() loop 2121c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate while (data.readNextHeader()) { 2131c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate String key = data.getKey(); 2141c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate int dataSize = data.getDataSize(); 2151c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate 2161c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate if (APP_DATA_KEY.equals(key)) { 2171c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate // It's our saved data, a flattened chunk of data all in 2181c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate // one buffer. Use some handy structured I/O classes to 2191c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate // extract it. 2201c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate byte[] dataBuf = new byte[dataSize]; 2211c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate data.readEntityData(dataBuf, 0, dataSize); 2221c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate ByteArrayInputStream baStream = new ByteArrayInputStream(dataBuf); 2231c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate DataInputStream in = new DataInputStream(baStream); 2241c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate 2251c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate mFilling = in.readInt(); 2261c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate mAddMayo = in.readBoolean(); 2271c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate mAddTomato = in.readBoolean(); 2281c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate 2291c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate // Now we are ready to construct the app's data file based 2301c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate // on the data we are restoring from. 2311c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate synchronized (BackupRestoreActivity.sDataLock) { 2321c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate RandomAccessFile file = new RandomAccessFile(mDataFile, "rw"); 2331c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate file.setLength(0L); 2341c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate file.writeInt(mFilling); 2351c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate file.writeBoolean(mAddMayo); 2361c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate file.writeBoolean(mAddTomato); 2371c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate } 2381c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate } else { 2391c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate // Curious! This entity is data under a key we do not 2401c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate // understand how to process. Just skip it. 2411c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate data.skipEntityData(); 2421c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate } 2431c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate } 2441c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate 2451c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate // The last thing to do is write the state blob that describes the 2461c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate // app's data as restored from backup. 2471c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate writeStateFile(newState); 2481c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate } 2491c0a20aeeb089971a624c102435755ba9ae74aabChristopher Tate} 250