• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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&lt;manifest ... &gt;
162    ...
163    &lt;application android:label="MyApplication"
164                 <b>android:backupAgent="MyBackupAgent"</b>&gt;
165        &lt;activity ... &gt;
166            ...
167        &lt;/activity&gt;
168    &lt;/application&gt;
169&lt;/manifest&gt;
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&lt;application android:label="MyApplication"
206             android:backupAgent="MyBackupAgent"&gt;
207    ...
208    &lt;meta-data android:name="com.google.android.backup.api_key"
209        android:value="AEdPqrEAAAAIDaYEVgU6DJnyJdBmU7KLH3kszDXLv_4DIsEIyQ" /&gt;
210&lt;/application&gt;
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()}&mdash;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&mdash;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&#64;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    &#64;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    &#64;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&#64;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&#64;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>&lt;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.