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