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