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