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