Home | History | Annotate | Download | only in data
      1 page.title=Data Backup
      2 @jd:body
      3 
      4 
      5 <div id="qv-wrapper">
      6 <div id="qv">
      7 
      8   <h2>Quickview</h2>
      9   <ul>
     10     <li>Back up your data to the cloud in case the user looses it</li>
     11     <li>Easily back up SharedPreferences and private files with BackupAgentHelper</li>
     12     <li>Requires API Level 8</li>
     13   </ul>
     14 
     15   <h2>In this document</h2>
     16   <ol>
     17     <li><a href="#Basics">The Basics</a></li>
     18     <li><a href="#BackupAgent">Extending BackupAgent</a>
     19       <ol>
     20         <li><a href="#RequiredMethods">Required Methods</a></li>
     21         <li><a href="#PerformingBackup">Performing backup</a></li>
     22         <li><a href="#PerformingRestore">Performing restore</a></li>
     23       </ol>
     24     </li>
     25     <li><a href="#BackupAgentHelper">Extending BackupAgentHelper</a>
     26       <ol>
     27         <li><a href="#SharedPreferences">Backing up SharedPreferences</a></li>
     28         <li><a href="#Files">Backing up Private Files</a></li>
     29       </ol>
     30     </li>
     31     <li><a href="#RestoreVersion">Checking the Restore Data Version</a></li>
     32     <li><a href="#RequestingBackup">Requesting Backup</a></li>
     33     <li><a href="#RequestingRestore">Requesting Restore</a></li>
     34     <li><a href="#DevelopingTesting">Developing and Testing Your Backup Agent</a></li>
     35   </ol>
     36 
     37   <h2>Key classes</h2>
     38   <ol>
     39     <li>{@link android.app.backup.BackupManager}</li>
     40     <li>{@link android.app.backup.BackupAgent}</li>
     41     <li>{@link android.app.backup.BackupAgentHelper}</li>
     42   </ol>
     43 
     44 </div>
     45 </div>
     46 
     47 <p>Android's {@link android.app.backup backup} service allows you to copy your persistent
     48 application data to a remote "cloud" storage, in order to provide a restore point for the
     49 application data and settings. If a user performs a factory reset or converts to a new
     50 Android-powered device, the system automatically restores your backup data when the application
     51 is re-installed. This way, your users are not required to reproduce their previous data or
     52 application settings. This process is completely transparent to the user and does not affect the
     53 functionality or user experience in your application.</p>
     54 
     55 <p>Android-powered devices that support the backup service provide a cloud storage area that
     56 saves your backup data and a backup transport that delivers your data to
     57 the storage area and back to the device. During a backup
     58 operation, Android's Backup Manager requests backup data from your application, then delivers it to
     59 the cloud storage using the backup transport. During a restore operation, the Backup Manager
     60 retrieves the backup data from the backup transport and returns it to your application
     61 so it can restore the data to the device. The backup service is <em>not</em> designed for data
     62 synchronization (you do not have access the backup data, except during a restore operation on the
     63 device).</p>
     64 
     65 <p>The cloud storage used for backup won't necessarily be the same on all Android-powered devices.
     66 The cloud storage and backup transport may differ between devices and service providers.
     67 Where the backup data is stored is transparent to your application, but you are assured that your
     68 application data cannot be read by other applications.</p>
     69 
     70 <p class="caution"><strong>Caution:</strong> Because the cloud storage and transport service can
     71 differ from device to device, Android makes no guarantees about the security of your data while
     72 using backup. You should be cautious about using backup to store sensitive data, such as usernames
     73 and passwords.</p>
     74 
     75 
     76 <h2 id="Basics">The Basics</h2>
     77 
     78 <p>To backup your application data, you need to implement a backup agent. Your backup
     79 agent is called by the Backup Manager to provide the data you want to back up. It is also called
     80 to restore your backup data when the application is re-installed. The Backup Manager handles all
     81 your data transactions with the cloud storage and your backup agent handles all your data
     82 transactions on the device.</p>
     83 
     84 <p>To implement a backup agent, you must:</p>
     85 
     86 <ol>
     87   <li>Declare your backup agent in your manifest file with the <a
     88 href="{@docRoot}guide/topics/manifest/application-element.html#agent">{@code
     89 android:backupAgent}</a> attribute.</li>
     90   <li>Define a backup agent by either:</p>
     91     <ol type="a">
     92       <li><a href="#backupAgent">Extending BackupAgent</a>
     93         <p>The {@link android.app.backup.BackupAgent} class provides the central interface with
     94 which your application communicates with the Backup Manager. If you extend this class
     95 directly, you must override {@link
     96 android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor)
     97 onBackup()} and {@link
     98 android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor)
     99 onRestore()} to handle the backup and restore operations for your data.</p>
    100         <p><em>Or</em></p>
    101       <li><a href="#backupAgentHelper">Extending BackupAgentHelper</a>
    102         <p>The {@link android.app.backup.BackupAgentHelper} class provides a convenient
    103 wrapper around the {@link android.app.backup.BackupAgent} class, which minimizes the amount of code
    104 you need to write. In your {@link android.app.backup.BackupAgentHelper}, you must use one or more
    105 "helper" objects, which automatically backup and restore certain types of data, so that you do not
    106 need to implement {@link
    107 android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor)
    108 onBackup()} and {@link
    109 android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor)
    110 onRestore()}.</p>
    111         <p>Android currently provides backup helpers that will backup and restore complete files
    112 from {@link android.content.SharedPreferences} and <a
    113 href="{@docRoot}guide/topics/data/data-storage.html#filesInternal">internal storage</a>.</p>
    114       </li>
    115     </ol>
    116   </li>
    117 </ol>
    118 
    119 
    120 
    121 
    122 <h2 id="BackupManifest">Declaring the Backup Agent in Your Manifest</h2>
    123 
    124 <p>This is the easiest step, so once you've decided on the class name for your backup agent, declare
    125 it in your manifest with the <a
    126 href="{@docRoot}guide/topics/manifest/application-element.html#agent">{@code
    127 android:backupAgent}</a> attribute in the <a
    128 href="{@docRoot}guide/topics/manifest/application-element.html">{@code
    129 &lt;application&gt;}</a> tag.</p>
    130 
    131 <p>For example:</p>
    132 
    133 <pre>
    134 &lt;manifest ... &gt;
    135     &lt;application android:label="MyApplication"
    136                  <b>android:backupAgent="MyBackupAgent"</b>&gt;
    137         &lt;activity ... &gt;
    138             ...
    139         &lt;/activity&gt;
    140     &lt;/application&gt;
    141 &lt;/manifest&gt;
    142 </pre>
    143 
    144 <p>Another attribute you might want to use is <a
    145 href="{@docRoot}guide/topics/manifest/application-element.html#restoreany">{@code
    146 android:restoreAnyVersion}</a>. This attribute takes a boolean value to indicate whether you
    147 want to restore the application data regardless of the current application version compared to the
    148 version that produced the backup data. (The default value is "{@code false}".) See <a
    149 href="#RestoreVersion">Checking the Restore Data Version</a> for more information.</p>
    150 
    151 <p class="note"><strong>Note:</strong> The backup service and the APIs you must use are
    152 available only on devices running API Level 8 (Android 2.2) or greater, so you should also
    153 set your <a
    154 href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code android:minSdkVersion}</a>
    155 attribute to "8". However, if you implement proper <a
    156 href="{@docRoot}resources/articles/backward-compatibility.html">backward compatibility</a> in
    157 your application, you can support this feature for devices running API Level 8 or greater, while
    158 remaining compatible with older devices.</p>
    159 
    160 
    161 
    162 
    163 
    164 <h2 id="BackupAgent">Extending BackupAgent</h2>
    165 
    166 <p>Most applications shouldn't need to extend the {@link android.app.backup.BackupAgent} class
    167 directly, but should instead <a href="BackupAgentHelper">extend BackupAgentHelper</a> to take
    168 advantage of the built-in helper classes that automatically backup and restore your files. However,
    169 you might want to extend {@link android.app.backup.BackupAgent} directly if you need to:</p>
    170 <ul>
    171   <li>Version your data format. For instance, if you anticipate the need to revise the
    172 format in which you write your application data, you can build a backup agent to cross-check your
    173 application version during a restore operation and perform any necessary compatibility work if the
    174 version on the device is different than that of the backup data. For more information, see <a
    175 href="#RestoreVersion">Checking the Restore Data Version</a>.</li>
    176   <li>Instead of backing up an entire file, you can specify the portions of data the should be
    177 backed up and how each portion is then restored to the device. (This can also help you manage
    178 different versions, because you read and write your data as unique entities, rather than
    179 complete files.)</li>
    180   <li>Back up data in a database. If you have an SQLite database that you want to restore when
    181 the user re-installs your application, you need to build a custom {@link
    182 android.app.backup.BackupAgent} that reads the appropriate data during a backup operation, then
    183 create your table and insert the data during a restore operation.</li>
    184 </ul>
    185 
    186 <p>If you don't need to perform any of the tasks above and want to back up complete files from
    187 {@link android.content.SharedPreferences} or <a
    188 href="{@docRoot}guide/topics/data/data-storage.html#filesInternal">internal storage</a>, you
    189 should skip to <a href="BackupAgentHelper">Extending BackupAgentHelper</a>.</p>
    190 
    191 
    192 
    193 <h3 id="RequiredMethods">Required Methods</h3>
    194 
    195 <p>When you create a backup agent by extending {@link android.app.backup.BackupAgent}, you
    196 must implement the following callback methods:</p>
    197 
    198 <dl>
    199   <dt>{@link
    200 android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor)
    201 onBackup()}</dt>
    202     <dd>The Backup Manager calls this method after you <a href="#RequestBackup">request a
    203 backup</a>. In this method, you read your application data from the device and pass the data you
    204 want to back up to the Backup Manager, as described below in <a href="#PerformingBackup">Performing
    205 backup</a>.</dd>
    206 
    207   <dt>{@link
    208 android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor)
    209 onRestore()}</dt>
    210     <dd>The Backup Manager calls this method during a restore operation (you can <a
    211 href="#RequestRestore">request a restore</a>, but the system automatically performs restore when the
    212 user re-installs your application). When it calls this method, the Backup Manager delivers your
    213 backup data, which you then restore to the device, as described below in <a
    214 href="#PerformingRestore">Performing restore</a>.</dd>
    215 </dl>
    216 
    217 
    218 
    219 <h3 id="PerformingBackup">Performing backup</h3>
    220 
    221 
    222 <p>When it's time to back up your application data, the Backup Manager calls your {@link
    223 android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor)
    224 onBackup()} method. This is where you must provide your application data to the Backup Manager so
    225 it can be saved to cloud storage.</p>
    226 
    227 <p>Only the Backup Manager can call your backup agent's {@link
    228 android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor)
    229 onBackup()} method. Each time that your application data changes and you want to perform a backup,
    230 you must request a backup operation by calling {@link
    231 android.app.backup.BackupManager#dataChanged()} (see <a href="#RequestingBackup">Requesting
    232 Backup</a> for more information). A backup request does not result in an immediate call to your
    233 {@link
    234 android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor)
    235 onBackup()} method. Instead, the Backup Manager waits for an appropriate time, then performs
    236 backup for all applications that have requested a backup since the last backup was performed.</p>
    237 
    238 <p class="note"><strong>Tip:</strong> While developing your application, you can initiate an
    239 immediate backup operation from the Backup Manager with the <a
    240 href="{@docRoot}guide/developing/tools/bmgr.html">bmgr tool</a>.</p>
    241 
    242 <p>When the Backup Manager calls your {@link
    243 android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor)
    244 onBackup()} method, it passes three parameters:</p>
    245 
    246 <dl>
    247   <dt>{@code oldState}</dt>
    248     <dd>An open, read-only {@link android.os.ParcelFileDescriptor} pointing to the last backup
    249 state provided by your application. This is not the backup data from cloud storage, but a
    250 local representation of the data that was backed up the last time {@link
    251 android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor)
    252 onBackup()} was called (as defined by {@code newState}, below, or from {@link
    253 android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor)
    254 onRestore()}&mdash;more about this in the next section). Because {@link
    255 android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor)
    256 onBackup()} does not allow you to read existing backup data in
    257 the cloud storage, you can use this local representation to determine whether your data has changed
    258 since the last backup.</dd>
    259   <dt>{@code data}</dt>
    260     <dd>A {@link android.app.backup.BackupDataOutput} object, which you use to deliver your backup
    261 data to the Backup Manager.</dd>
    262   <dt>{@code newState}</dt>
    263     <dd>An open, read/write {@link android.os.ParcelFileDescriptor} pointing to a file in which
    264 you must write a representation of the data that you delivered to {@code data} (a representation
    265 can be as simple as the last-modified timestamp for your file). This object is
    266 returned as {@code oldState} the next time the Backup Manager calls your {@link
    267 android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor)
    268 onBackup()} method. If you do not write your backup data to {@code newState}, then {@code oldState}
    269 will point to an empty file next time Backup Manager calls {@link
    270 android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor)
    271 onBackup()}.</dd>
    272 </dl>
    273 
    274 <p>Using these parameters, you should implement your {@link
    275 android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor)
    276 onBackup()} method to do the following:</p>
    277 
    278 <ol>
    279   <li>Check whether your data has changed since the last backup by comparing {@code oldState} to
    280 your current data. How you read data in {@code oldState} depends on how you originally wrote it to
    281 {@code newState} (see step 3). The easiest way to record the state of a file is with its
    282 last-modified timestamp. For example, here's how you can read and compare a timestamp from {@code
    283 oldState}:
    284     <pre>
    285 // Get the oldState input stream
    286 FileInputStream instream = new FileInputStream(oldState.getFileDescriptor());
    287 DataInputStream in = new DataInputStream(instream);
    288 
    289 try {
    290     // Get the last modified timestamp from the state file and data file
    291     long stateModified = in.readLong();
    292     long fileModified = mDataFile.lastModified();
    293 
    294     if (stateModified != fileModified) {
    295         // The file has been modified, so do a backup
    296         // Or the time on the device changed, so be safe and do a backup
    297     } else {
    298         // Don't back up because the file hasn't changed
    299         return;
    300     }
    301 } catch (IOException e) {
    302     // Unable to read state file... be safe and do a backup
    303 }
    304 </pre>
    305     <p>If nothing has changed and you don't need to back up, skip to step 3.</p>
    306   </li>
    307   <li>If your data has changed, compared to {@code oldState}, write the current data to
    308 {@code data} to back it up to the cloud storage.
    309     <p>You must write each chunk of data as an "entity" in the {@link
    310 android.app.backup.BackupDataOutput}. An entity is a flattened binary data
    311 record that is identified by a unique key string. Thus, the data set that you back up is
    312 conceptually a set of key-value pairs.</p>
    313     <p>To add an entity to your backup data set, you must:</p>
    314     <ol>
    315       <li>Call {@link android.app.backup.BackupDataOutput#writeEntityHeader(String,int)
    316 writeEntityheader()}, passing a unique string key for the data you're about to write and the data
    317 size.</li>
    318       <li>Call {@link android.app.backup.BackupDataOutput#writeEntityData(byte[],int)
    319 writeEntityData()}, passing a byte buffer that contains your data and the number of bytes to write
    320 from the buffer (which should match the size passed to {@link
    321 android.app.backup.BackupDataOutput#writeEntityHeader(String,int) writeEntityHeader()}).</li>
    322     </ol>
    323     <p>For example, the following code flattens some data into a byte stream and writes it into a
    324 single entity:</p>
    325     <pre>
    326 // Create buffer stream and data output stream for our data
    327 ByteArrayOutputStream bufStream = new ByteArrayOutputStream();
    328 DataOutputStream outWriter = new DataOutputStream(bufStream);
    329 // Write structured data
    330 outWriter.writeString(playerName);
    331 outWriter.writeInt(playerScore);
    332 // Send the data to the Backup Manager via the BackupDataOutput
    333 byte[] buffer = bufStream.toByteArray();
    334 int len = buffer.length;
    335 data.writeEntityHeader(TOPSCORE_BACKUP_KEY, len);
    336 data.writeEntityData(buffer, len);
    337 </pre>
    338     <p>Perform this for each piece of data that you want to back up. How you divide your data into
    339 entities is up to you (and you might use just one entity).</p>
    340   </li>
    341   <li>Whether or not you perform a backup (in step 2), write a representation of the current data to
    342 the {@code newState} {@link android.os.ParcelFileDescriptor}. The Backup Manager retains this object
    343 locally as a representation of the data that is currently backed up. It passes this back to you as
    344 {@code oldState} the next time it calls {@link
    345 android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor)
    346 onBackup()} so you can determine whether another backup is necessary (as handled in step 1). If you
    347 do not write the current data state to this file, then
    348 {@code oldState} will be empty during the next callback.
    349     <p>Again, the following example saves a representation of the data using the file's
    350 last-modified timestamp:</p>
    351     <pre>
    352 FileOutputStream outstream = new FileOutputStream(stateFile.getFileDescriptor());
    353 DataOutputStream out = new DataOutputStream(outstream);
    354 
    355 long modified = mDataFile.lastModified();
    356 out.writeLong(modified);
    357 </pre>
    358   </li>
    359 </ol>
    360 
    361 <p class="caution"><strong>Caution:</strong> If your application data is saved to a file, make sure
    362 that you use synchronized statements while accessing the file so that your backup agent does not
    363 read the file while an Activity in your application is also writing the file.</p>
    364 
    365 
    366 
    367 
    368 <h3 id="PerformingRestore">Performing restore</h3>
    369 
    370 <p>When it's time to restore your application data, the Backup Manager calls your backup
    371 agent's {@link android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor)
    372 onRestore()} method. When it calls this method, the Backup Manager delivers your backup data so
    373 you can restore it onto the device.</p>
    374 
    375 <p>Only the Backup Manager can call {@link
    376 android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor)
    377 onRestore()}, which happens automatically when the system installs your application and
    378 finds existing backup data. However, you can request a restore operation for
    379 your application by calling {@link
    380 android.app.backup.BackupManager#requestRestore(RestoreObserver) requestRestore()} (see <a
    381 href="#RequestingRestore">Requesting restore</a> for more information).</p>
    382 
    383 <p class="note"><strong>Note:</strong> While developing your application, you can also request a
    384 restore operation with the <a href="{@docRoot}guide/developing/tools/bmgr.html">bmgr
    385 tool</a>.</p>
    386 
    387 <p>When the Backup Manager calls your {@link
    388 android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor)
    389 onRestore()} method, it passes three parameters:</p>
    390 
    391 <dl>
    392   <dt>{@code data}</dt>
    393     <dd>A {@link android.app.backup.BackupDataInput}, which allows you to read your backup
    394 data.</dd>
    395   <dt>{@code appVersionCode}</dt>
    396     <dd>An integer representing the value of your application's <a
    397 href="{@docRoot}guide/topics/manifest/manifest-element.html#vcode">{@code android:versionCode}</a>
    398 manifest attribute, as it was when this data was backed up. You can use this to cross-check the
    399 current application version and determine if the data format is compatible. For more
    400 information about using this to handle different versions of restore data, see the section
    401 below about <a href="#RestoreVersion">Checking the Restore Data Version</a>.</dd>
    402   <dt>{@code newState}</dt>
    403     <dd>An open, read/write {@link android.os.ParcelFileDescriptor} pointing to a file in which
    404 you must write the final backup state that was provided with {@code data}. This object is
    405 returned as {@code oldState} the next time {@link
    406 android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor)
    407 onBackup()} is called. Recall that you must also write the same {@code newState} object in the
    408 {@link
    409 android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor)
    410 onBackup()} callback&mdash;also doing it here ensures that the {@code oldState} object given to
    411 {@link
    412 android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor)
    413 onBackup()} is valid even the first time {@link
    414 android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor)
    415 onBackup()} is called after the device is restored.</dd>
    416 </dl>
    417 
    418 <p>In your implementation of {@link
    419 android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor)
    420 onRestore()}, you should call {@link android.app.backup.BackupDataInput#readNextHeader()} to iterate
    421 through all entities in the data set. For each entity found, do the following:</p>
    422 
    423 <ol>
    424   <li>Get the entity key with {@link android.app.backup.BackupDataInput#getKey()}.</li>
    425   <li>Compare the entity key to a list of known key values that you should have declared as static
    426 final strings inside your {@link android.app.backup.BackupAgent} class. When the key matches one of
    427 your known key strings, enter into a statement to extract the entity data and save it to the device:
    428     <ol>
    429       <li>Get the entity data size with {@link
    430 android.app.backup.BackupDataInput#getDataSize()} and create a byte array of that size.</li>
    431       <li>Call {@link android.app.backup.BackupDataInput#readEntityData(byte[],int,int)
    432 readEntityData()} and pass it the byte array, which is where the data will go, and specify the
    433 start offset and the size to read.</li>
    434       <li>Your byte array is now full and you can read the data and write it to the device
    435 however you like.</li>
    436     </ol>
    437   </li>
    438   <li>After you read and write your data back to the device, write the state of your data to the
    439 {@code newState} parameter the same as you do during {@link
    440 android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor)
    441 onBackup()}.
    442 </ol>
    443 
    444 <div class="special">
    445 <p>For an example implementation of {@link android.app.backup.BackupAgent}, see the <a
    446 href="{@docRoot}resources/samples/BackupRestore/src/com/example/android/backuprestore/ExampleAgent.html">{@code
    447 ExampleAgent}</a> class in the <a
    448 href="{@docRoot}resources/samples/BackupRestore/index.html">Backup and Restore</a> sample
    449 application.</p>
    450 </div>
    451 
    452 
    453 
    454 
    455 
    456 
    457 <h2 id="BackupAgentHelper">Extending BackupAgentHelper</h2>
    458 
    459 <p>You should build your backup agent using {@link android.app.backup.BackupAgentHelper} if you want
    460 to back up complete files (from either {@link android.content.SharedPreferences} or <a
    461 href="{@docRoot}guide/topics/data/data-storage.html#filesInternal">internal storage</a>).
    462 Building your backup agent with {@link android.app.backup.BackupAgentHelper} requires far less
    463 code than extending {@link android.app.backup.BackupAgent}, because you don't have to implement
    464 {@link
    465 android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor)
    466 onBackup()} and {@link
    467 android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor)
    468 onRestore()}.</p>
    469 
    470 <p>Your implementation of {@link android.app.backup.BackupAgentHelper} must
    471 use one or more backup helpers. A backup helper is a specialized
    472 component that {@link android.app.backup.BackupAgentHelper} summons to perform backup and
    473 restore operations for a particular type of data. The Android framework currently provides two
    474 different helpers:</p>
    475 <ul>
    476   <li>{@link android.app.backup.SharedPreferencesBackupHelper} to backup {@link
    477 android.content.SharedPreferences} files.</li>
    478   <li>{@link android.app.backup.FileBackupHelper} to backup files from <a
    479 href="{@docRoot}guide/topics/data/data-storage.html#filesInternal">internal storage</a>.</li>
    480 </ul>
    481 
    482 <p>You can include multiple helpers in your {@link android.app.backup.BackupAgentHelper}, but only
    483 one helper is needed for each data type. That is, if you have multiple {@link
    484 android.content.SharedPreferences} files, then you need only one {@link
    485 android.app.backup.SharedPreferencesBackupHelper}.</p>
    486 
    487 <p>For each helper you want to add to your {@link android.app.backup.BackupAgentHelper}, you must do
    488 the following during your {@link android.app.backup.BackupAgent#onCreate()} method:</p>
    489 <ol>
    490   <li>Instantiate in instance of the desired helper class. In the class constructor, you must
    491 specify the appropriate file(s) you want to backup.</li>
    492   <li>Call {@link android.app.backup.BackupAgentHelper#addHelper(String,BackupHelper) addHelper()}
    493 to add the helper to your {@link android.app.backup.BackupAgentHelper}.</li>
    494 </ol>
    495 
    496 <p>The following sections describe how to create a backup agent using each of the available
    497 helpers.</p>
    498 
    499 
    500 
    501 <h3 id="SharedPreferences">Backing up SharedPreferences</h3>
    502 
    503 <p>When you instantiate a {@link android.app.backup.SharedPreferencesBackupHelper}, you must the
    504 name of one or more {@link android.content.SharedPreferences} files.</p>
    505 
    506 <p>For example, to back up a {@link android.content.SharedPreferences} file named
    507 "user_preferences", a complete backup agent using {@link android.app.backup.BackupAgentHelper} looks
    508 like this:</p>
    509 
    510 <pre>
    511 public class MyPrefsBackupAgent extends BackupAgentHelper {
    512     // The name of the SharedPreferences file
    513     static final String PREFS = "user_preferences";
    514 
    515     // A key to uniquely identify the set of backup data
    516     static final String PREFS_BACKUP_KEY = "prefs";
    517 
    518     // Allocate a helper and add it to the backup agent
    519     void onCreate() {
    520         SharedPreferencesBackupHelper helper = new SharedPreferencesBackupHelper(this, PREFS);
    521         addHelper(PREFS_BACKUP_KEY, helper);
    522     }
    523 }
    524 </pre>
    525 
    526 <p>That's it! That's your entire backup agent. The {@link
    527 android.app.backup.SharedPreferencesBackupHelper} includes all the code
    528 needed to backup and restore a {@link android.content.SharedPreferences} file.</p>
    529 
    530 <p>When the Backup Manager calls {@link
    531 android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor)
    532 onBackup()} and {@link
    533 android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor)
    534 onRestore()}, {@link android.app.backup.BackupAgentHelper} calls your backup helpers to perform
    535 backup and restore for your specified files.</p>
    536 
    537 <p class="note"><strong>Note:</strong> {@link android.content.SharedPreferences} are threadsafe, so
    538 you can safely read and write the shared preferences file from your backup agent and
    539 other activities.</p>
    540 
    541 
    542 
    543 <h3 id="Files">Backing up other files</h3>
    544 
    545 <p>When you instantiate a {@link android.app.backup.FileBackupHelper}, you must include the name of
    546 one or more files that are saved to your application's <a
    547 href="{@docRoot}guide/topics/data/data-storage.html#filesInternal">internal storage</a>
    548 (as specified by {@link android.content.ContextWrapper#getFilesDir()}, which is the same
    549 location where {@link android.content.Context#openFileOutput(String,int) openFileOutput()} writes
    550 files).</p>
    551 
    552 <p>For example, to backup two files named "scores" and "stats," a backup agent using {@link
    553 android.app.backup.BackupAgentHelper} looks like this:</p>
    554 
    555 <pre>
    556 public class MyFileBackupAgent extends BackupAgentHelper {
    557     // The name of the SharedPreferences file
    558     static final String TOP_SCORES = "scores";
    559     static final String PLAYER_STATS = "stats";
    560 
    561     // A key to uniquely identify the set of backup data
    562     static final String FILES_BACKUP_KEY = "myfiles";
    563 
    564     // Allocate a helper and add it to the backup agent
    565     void onCreate() {
    566         FileBackupHelper helper = new FileBackupHelper(this, TOP_SCORES, PLAYER_STATS);
    567         addHelper(FILES_BACKUP_KEY, helper);
    568     }
    569 }
    570 </pre>
    571 
    572 <p>The {@link android.app.backup.FileBackupHelper} includes all the code necessary to backup and
    573 restore files that are saved to your application's <a
    574 href="{@docRoot}guide/topics/data/data-storage.html#filesInternal">internal storage</a>..</p>
    575 
    576 <p>However, reading and writing to files on internal storage is <strong>not threadsafe</strong>. To
    577 ensure that your backup agent does not read or write your files at the same time as your activities,
    578 you must use synchronized statements each time you perform a read or write. For example,
    579 in any Activity where you read and write the file, you need an object to use as the intrinsic
    580 lock for the synchronized statements:</p>
    581 
    582 <div class="sidebox-wrapper">
    583 <div class="sidebox">
    584 <p><strong>Interesting Fact:</strong></p>
    585 <p>A zero-length array is lighter-weight than a normal Object, so it's great for an
    586 intrinsic lock.</p>
    587 </div>
    588 </div>
    589 
    590 <pre>
    591 // Object for intrinsic lock
    592 static final Object[] sDataLock = new Object[0];
    593 </pre>
    594 
    595 <p>Then create a synchronized statement with this lock each time you read or write the files. For
    596 example, here's a synchronized statement for writing the latest score in a game to a file:</p>
    597 
    598 <pre>
    599 try {
    600     synchronized (MyActivity.sDataLock) {
    601         File dataFile = new File({@link android.content.Context#getFilesDir()}, TOP_SCORES);
    602         RandomAccessFile raFile = new RandomAccessFile(dataFile, "rw");
    603         raFile.writeInt(score);
    604     }
    605 } catch (IOException e) {
    606     Log.e(TAG, "Unable to write to file");
    607 }
    608 </pre>
    609 
    610 <p>You should synchronize your read statements with the same lock.</p>
    611 
    612 <p>Then, in your {@link android.app.backup.BackupAgentHelper}, you must override {@link
    613 android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor)
    614 onBackup()} and {@link
    615 android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor)
    616 onRestore()} to synchronize the backup and restore operations with the same
    617 intrinsic lock. For example, the {@code MyFileBackupAgent} example from above needs the following
    618 methods:</p>
    619 
    620 <pre>
    621 &#64;Override
    622 public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
    623           ParcelFileDescriptor newState) throws IOException {
    624     // Hold the lock while the FileBackupHelper performs backup
    625     synchronized (MyActivity.sDataLock) {
    626         super.onBackup(oldState, data, newState);
    627     }
    628 }
    629 
    630 &#64;Override
    631 public void onRestore(BackupDataInput data, int appVersionCode,
    632         ParcelFileDescriptor newState) throws IOException {
    633     // Hold the lock while the FileBackupHelper restores the file
    634     synchronized (MyActivity.sDataLock) {
    635         super.onRestore(data, appVersionCode, newState);
    636     }
    637 }
    638 </pre>
    639 
    640 <p>That's it. All you need to do is add your {@link android.app.backup.FileBackupHelper} in the
    641 {@link android.app.backup.BackupAgent#onCreate()} method and override {@link
    642 android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor)
    643 onBackup()} and {@link
    644 android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor)
    645 onRestore()} to synchronize read and write operations.</p>
    646 
    647 <div class="special">
    648 <p>For an example implementation of {@link
    649 android.app.backup.BackupAgentHelper} with {@link android.app.backup.FileBackupHelper}, see the
    650 {@code FileHelperExampleAgent} class in the <a
    651 href="{@docRoot}resources/samples/BackupRestore/index.html">Backup and Restore</a> sample
    652 application.</p>
    653 </div>
    654 
    655 
    656 
    657 
    658 
    659 
    660 <h2 id="RestoreVersion">Checking the Restore Data Version</h2>
    661 
    662 <p>When the Backup Manager saves your data to cloud storage, it automatically includes the version
    663 of your application, as defined by your manifest file's <a
    664 href="{@docRoot}guide/topics/manifest/manifest-element.html#vcode">{@code android:versionCode}</a>
    665 attribute. Before the Backup Manager calls your backup agent to restore your data, it
    666 looks at the <a
    667 href="{@docRoot}guide/topics/manifest/manifest-element.html#vcode">{@code
    668 android:versionCode}</a> of the installed application and compares it to the value
    669 recorded in the restore data set. If the version recorded in the restore data set is
    670 <em>newer</em> than the application version on the device, then the user has downgraded their
    671 application. In this case, the Backup Manager will abort the restore operation for your application
    672 and not call your {@link
    673 android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) onRestore()}
    674 method, because the restore set is considered meaningless to an older version.</p>
    675 
    676 <p>You can override this behavior with the <a
    677 href="{@docRoot}guide/topics/manifest/application-element.html#restoreany">{@code
    678 android:restoreAnyVersion}</a> attribute. This attribute is either "{@code true}" or "{@code
    679 false}" to indicate whether you want to restore the application regardless of the restore set
    680 version. The default value is "{@code false}". If you define this to be "{@code true}" then the
    681 Backup Manager will ignore the <a
    682 href="{@docRoot}guide/topics/manifest/manifest-element.html#vcode">{@code android:versionCode}</a>
    683 and call your {@link
    684 android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) onRestore()}
    685 method in all cases. In doing so, you can manually check for the version difference in your {@link
    686 android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) onRestore()}
    687 method and take any steps necessary to make the data compatible if the versions conflict.</p>
    688 
    689 <p>To help you handle different versions during a restore operation, the {@link
    690 android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) onRestore()}
    691 method passes you the version code included with the restore data set as the {@code appVersionCode}
    692 parameter. You can then query the current application's version code with the {@link
    693 android.content.pm.PackageInfo#versionCode PackageInfo.versionCode} field. For example:</p>
    694 
    695 <pre>
    696 PackageInfo info;
    697 try {
    698     String name = {@link android.content.ContextWrapper#getPackageName() getPackageName}();
    699     info = {@link android.content.ContextWrapper#getPackageManager
    700 getPackageManager}().{@link android.content.pm.PackageManager#getPackageInfo(String,int)
    701 getPackageInfo}(name,0);
    702 } catch (NameNotFoundException nnfe) {
    703     info = null;
    704 }
    705 
    706 int version;
    707 if (info != null) {
    708     version = info.versionCode;
    709 }
    710 </pre>
    711 
    712 <p>Then simply compare the {@code version} acquired from {@link android.content.pm.PackageInfo}
    713 to the {@code appVersionCode} passed into {@link
    714 android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) onRestore()}.
    715 </p>
    716 
    717 <p class="caution"><strong>Caution:</strong> Be certain you understand the consequences of setting
    718 <a href="{@docRoot}guide/topics/manifest/application-element.html#restoreany">{@code
    719 android:restoreAnyVersion}</a> to "{@code true}" for your application. If each version of your
    720 application that supports backup does not properly account for variations in your data format during
    721 {@link
    722 android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) onRestore()},
    723 then the data on the device could be saved in a format incompatible with the version currently
    724 installed on the device.</p>
    725 
    726 
    727 
    728 <h2 id="RequestingBackup">Requesting Backup</h2>
    729 
    730 <p>You can request a backup operation at any time by calling {@link
    731 android.app.backup.BackupManager#dataChanged()}. This method notifies the Backup Manager that you'd
    732 like to backup your data using your backup agent. The Backup Manager then calls your backup
    733 agent's {@link
    734 android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor)
    735 onBackup()} method at an opportune time in the future. Typically, you should
    736 request a backup each time your data changes (such as when the user changes an application
    737 preference that you'd like to back up). If you call {@link
    738 android.app.backup.BackupManager#dataChanged()} several times consecutively, before the Backup
    739 Manager requests a backup from your agent, your agent still receives just one call to {@link
    740 android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor)
    741 onBackup()}.</p>
    742 
    743 <p class="note"><strong>Note:</strong> While developing your application, you can request a
    744 backup and initiate an immediate backup operation with the <a
    745 href="{@docRoot}guide/developing/tools/bmgr.html">bmgr
    746 tool</a>.</p>
    747 
    748 
    749 <h2 id="RequestingRestore">Requesting Restore</h2>
    750 
    751 <p>During the normal life of your application, you shouldn't need to request a restore operation.
    752 They system automatically checks for backup data and performs a restore when your application is
    753 installed. However, you can manually request a restore operation by calling {@link
    754 android.app.backup.BackupManager#requestRestore(RestoreObserver) requestRestore()}, if necessary. In
    755 which case, the Backup Manager calls your {@link
    756 android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) onRestore()}
    757 implementation, passing the data from the current set of backup data.</p>
    758 
    759 <p class="note"><strong>Note:</strong> While developing your application, you can request a
    760 restore operation with the <a href="{@docRoot}guide/developing/tools/bmgr.html">bmgr
    761 tool</a>.</p>
    762 
    763 
    764 <h2 id="DevelopingTesting">Developing and Testing Your Backup Agent</h2>
    765 
    766 <p>To develop and test your backup agent:</p>
    767 <ul>
    768   <li>Set your build target to a platform using API Level 8 or higher</li>
    769   <li>Run your application on a suitable Android system image:
    770     <ul>
    771       <li>If using the emulator, create and use an AVD with the Google APIs add-on (API Level
    772 8) &mdash; the Google APIs add-on is available as an SDK component through the SDK and AVD
    773 Manager</li>
    774       <li>If using a device, the device must be running Android 2.2 or greater and have Android
    775 Market built in</li>
    776     </ul>
    777   </li>
    778   <li>Test your backup agent using the <a href="{@docRoot}guide/developing/tools/bmgr.html">{@code
    779 bmgr}</a> tool to initiate backup and restore operations</li>
    780 </ul>
    781 
    782