diff options
-rw-r--r-- | docs/html/_redirects.yaml | 10 | ||||
-rw-r--r-- | docs/html/guide/_book.yaml | 7 | ||||
-rw-r--r-- | docs/html/guide/guide_toc.cs | 11 | ||||
-rw-r--r-- | docs/html/guide/topics/data/autobackup.jd | 257 | ||||
-rw-r--r-- | docs/html/guide/topics/data/backup.jd | 958 | ||||
-rw-r--r-- | docs/html/guide/topics/data/images/backup-framework.png | bin | 0 -> 43423 bytes | |||
-rw-r--r-- | docs/html/guide/topics/data/index.jd | 18 | ||||
-rw-r--r-- | docs/html/guide/topics/data/keyvaluebackup.jd | 884 | ||||
-rw-r--r-- | docs/html/guide/topics/data/testingbackup.jd | 181 | ||||
-rw-r--r-- | docs/html/training/_book.yaml | 12 | ||||
-rw-r--r-- | docs/html/training/backup/autosyncapi.jd | 370 | ||||
-rw-r--r-- | docs/html/training/backup/backupapi.jd | 200 | ||||
-rw-r--r-- | docs/html/training/backup/index.jd | 47 | ||||
-rw-r--r-- | docs/html/training/training_toc.cs | 18 |
14 files changed, 1378 insertions, 1595 deletions
diff --git a/docs/html/_redirects.yaml b/docs/html/_redirects.yaml index 8ddb98239038..10afc8eb5d3c 100644 --- a/docs/html/_redirects.yaml +++ b/docs/html/_redirects.yaml @@ -430,7 +430,13 @@ redirects: - from: /training/cloudsync/aesync.html to: /google/gcm/index.html - from: /training/cloudsync/index.html - to: /training/backup/index.html + to: /guide/topics/data/backup.html +- from: /training/backup/index.html + to: /guide/topics/data/backup.html +- from: /training/backup/autosyncapi.html + to: /guide/topics/data/autobackup.html +- from: /training/backup/backupapi.html + to: /guide/topics/data/keyvaluebackup.html - from: /training/basics/location/... to: /training/location/... - from: /training/monetization/index.html @@ -796,7 +802,7 @@ redirects: - from: /preview/features/app-linking.html to: /training/app-links/index.html - from: /preview/backup/index.html - to: /training/backup/autosyncapi.html + to: /guide/topics/data/backup/autobackup.html - from: /preview/features/power-mgmt.html to: /training/monitoring-device-state/doze-standby.html - from: /preview/dev-community diff --git a/docs/html/guide/_book.yaml b/docs/html/guide/_book.yaml index 20ee4838fab5..6889fe090511 100644 --- a/docs/html/guide/_book.yaml +++ b/docs/html/guide/_book.yaml @@ -396,6 +396,13 @@ toc: path: /guide/topics/data/data-storage.html - title: Data Backup path: /guide/topics/data/backup.html + section: + - title: Auto Backup + path: /guide/topics/data/autobackup.html + - title: Key/Value Backup + path: /guide/topics/data/keyvaluebackup.html + - title: Testing Backup and Restore + path: /guide/topics/data/testingbackup.html - title: App Install Location path: /guide/topics/data/install-location.html diff --git a/docs/html/guide/guide_toc.cs b/docs/html/guide/guide_toc.cs index 9257a76e93f2..8fe3f201fc2e 100644 --- a/docs/html/guide/guide_toc.cs +++ b/docs/html/guide/guide_toc.cs @@ -545,9 +545,16 @@ <li><a href="<?cs var:toroot ?>guide/topics/data/data-storage.html"> <span class="en">Storage Options</span> </a></li> - <li><a href="<?cs var:toroot ?>guide/topics/data/backup.html"> + <li class="nav-section"> + <div class="nav-section-header"><a href="<?cs var:toroot ?>guide/topics/data/backup.html"> <span class="en">Data Backup</span> - </a></li> + </a></div> + <ul> + <li><a href="<?cs var:toroot ?>guide/topics/data/autobackup.html">Auto Backup</a></li> + <li><a href="<?cs var:toroot ?>guide/topics/data/keyvaluebackup.html">Key/Value Backup</a></li> + <li><a href="<?cs var:toroot ?>guide/topics/data/testingbackup.html">Testing Backup and Restore</a></li> + </ul> + </li> <li><a href="<?cs var:toroot ?>guide/topics/data/install-location.html"> <span class="en">App Install Location</span> </a></li> diff --git a/docs/html/guide/topics/data/autobackup.jd b/docs/html/guide/topics/data/autobackup.jd new file mode 100644 index 000000000000..3be09d712884 --- /dev/null +++ b/docs/html/guide/topics/data/autobackup.jd @@ -0,0 +1,257 @@ +page.title=Auto Backup for Apps +page.tags=backup, marshmallow, androidm +page.keywords=backup, autobackup +page.image=images/cards/card-auto-backup_2x.png + +@jd:body + +<div id="qv-wrapper"> +<div id="qv"> + <h2>In this document</h2> + <ol> + <li><a href="#Files">Files that are backed up</a></li> + <li><a href="#BackupLocation">Backup location</a></li> + <li><a href="#BackupSchedule">Backup schedule</a></li> + <li><a href="#RestoreSchedule">Restore schedule</a></li> + <li><a href="#EnablingAutoBackup">Enabling and disabling Auto Backup</a></li> + <li><a href="#IncludingFiles">Including and excluding files</a><ul> + <li><a href="#XMLSyntax">XML config syntax</a></li> + </ul></li> + <li><a href="#ImplementingBackupAgent">Implementing BackupAgent</a></li> + </ol> + + <h2>Key classes</h2> + <ol> + <li>{@link android.app.backup.BackupAgent}</li> + <li><a href="{@docRoot}reference/android/R.attr.html">R.attr</a></li> + </ol> + +</div> +</div> + +Since Android 6.0 (API 23), Android has offered the <em>Auto Backup for Apps</em> feature as +a way for developers to quickly add backup functionality to their apps. Auto +Backup preserves app data by uploading it to the user’s Google Drive account. +The amount of data is limited to 25MB per user of your app and there is no +charge for storing backup data. + +<h2 id="Files">Files that are backed up</h2> +<p>By default, Auto Backup includes files in most of the directories that are +assigned to your app by the system: +<ul> + <li>Shared preferences files. + <li>Files in the directory returned by {@link android.content.Context#getFilesDir()}. + <li>Files in the directory returned by {@link android.content.Context#getDatabasePath(String)}, + which also includes files created with the + {@link android.database.sqlite.SQLiteOpenHelper} class. + <li>Files in directories created with {@link android.content.Context#getDir(String,int)}. + <li>Files on external storage in the directory returned by + {@link android.content.Context#getExternalFilesDir(String)}.</li></ul> + +<p>Auto Backup excludes files in directories returned by + {@link android.content.Context#getCacheDir()}, + {@link android.content.Context#getCodeCacheDir()}, or + {@link android.content.Context#getNoBackupFilesDir()}. The files saved + in these locations are only needed temporarily, or are intentionally + excluded from backup operations. + +<p>You can configure your app to include and exclude particular files. +For more information, see the <a href="#IncludingFiles">Include and exclude files</a> +section. + +<h2 id="BackupLocation">Backup location</h2> +<p>Backup data is stored in a private folder in the user's Google Drive account, +limited to 25MB per app. The saved data does not count towards the user's +personal Google Drive quota. Only the most recent backup is stored. When a +backup is made, the previous backup (if one exists) is deleted. + +<p>Users can see a list of apps that have been backed up in the Google Drive app under +<strong>Settings -> Auto Backup for apps -> Manage backup</strong>. The +backup data cannot be read by the user or other applications on the device. + +<p>Backups from each device-setup-lifetime are stored in separate datasets +as shown in the following examples: +<ul> + <li>If the user owns two devices, then a backup dataset exists for each device. + <li>If the user factory resets a device and then sets up the device with the + same account, the backup is stored in a new dataset. Obsolete datasets are + automatically deleted after a period of inactivity.</li></ul> + +<p class="caution"><strong>Caution:</strong> Once the amount of data reaches +25MB, the app is banned from sending data to the +cloud, even if the amount of data later falls under the 25MB threshold. The ban +affects only the offending device (not other devices that the user owns) and +lasts for the entire device-setup-lifetime. For example, if the user removes and +reinstalls the application, the ban is still in effect. The ban is lifted when +the user performs factory reset on the device. + +<h2 id="BackupSchedule">Backup schedule</h2> +<p>Backups occur automatically when all of the following conditions are met: +<ul> + <li>The user has enabled backup on the device in <strong>Settings</strong> > + <strong>Backup & Reset</strong>. + <li>At least 24 hours have elapsed since the last backup. + <li>The device is idle and charging. + <li>The device is connected to a Wi-Fi network. If the device is never connected + to a wifi network, then Auto Backup never occurs.</li></ul> + +<p>In practice, these conditions occur roughly every night. To conserve network +bandwidth, upload takes place only if app data has changed. + +<p>During Auto Backup, the system shuts down the app to make sure it is no longer +writing to the file system. By default, the backup system ignores apps that are +running in the foreground because users would notice their apps being shut down. +You can override the default behavior by setting the +<a href="{@docRoot}reference/android/R.attr.html#backupInForeground">backupInForeground</a> +attribute to true. + +<p>To simplify testing, Android includes tools that let you manually initiate +a backup of your app. For more information, see +<a href="{@docRoot}guide/topics/data/testingbackup.html">Testing Backup and Restore</a>. + +<h2 id="RestoreSchedule">Restore schedule</h2> +<p>Data is restored whenever the app is installed, either from the Play store, +during device setup (when the system installs previously installed apps), or +from running adb install. The restore operation occurs after the APK is +installed, but before the app is available to be launched by the user. + +<p>During the initial device setup wizard, the user is shown a list of available backup +datasets and is asked which one to restore the data from. Whichever backup +dataset is selected becomes the ancestral dataset for the device. The device can +restore from either its own backups or the ancestral dataset. The device +prioritize its own backup if backups from both sources are available. If the +user didn't go through the device setup wizard, then the device can restore only from +its own backups. + +<p>To simplify testing, Android includes tools that let you manually initiate +a restore of your app. For more information, see +<a href="{@docRoot}guide/topics/data/testingbackup.html">Testing Backup and Restore</a>. + +<h2 id="EnablingAutoBackup">Enabling and disabling backup</h2> +<p>Apps that target Android 6.0 (API level 23) or higher automatically participate +in Auto Backup. This is because the +<a href="{@docRoot}reference/android/R.attr.html#allowBackup">android:allowBackup</a> +attribute, which enables/disables backup, defaults to <code>true</code> if omitted. +To avoid confusion, we recommend you explicitly set the attribute in the <code><application></code> +element of your <code>AndroidManifest.xml</code>. For example: + +<pre class="prettyprint"><application ... + android:allowBackup="true"> +</app></pre> + +<p>To disable Auto Backup, add either of the following attributes to the +application element in your manifest file: + +<ul> + <li>set <code>android:allowBackup</code> to <code>false</code>. This completely disables data + backup. You may want to disable backups when your app can recreate its state + through some other mechanism or when your app deals with sensitive + information that should not be backed up.</li> + <li>set <code>android:allowBackup</code> to <code>true</code> and + <code>android:fullBackupOnly</code> to <code>false</code>. With these settings, + your app always participates in Key/Value Backup, even when running on devices that + support Auto Backup.</li></ul> + +<h2 id="IncludingFiles">Including and excluding files</h2> +<p>By default, the system backs up almost all app data. For more information, +see <a href="#Files">Files that are backed up</a>. This section shows you how to +define custom XML rules to control what gets backed up. + +<ol> + <li>In <code>AndroidManifest.xml</code>, add the <a href="{@docRoot}reference/android/R.attr.html#fullBackupContent">android:fullBackupContent</a> attribute to the + <code><application></code> element. This attribute points to an XML file that contains backup + rules. For example: + <pre class="prettyprint"><application ... + android:fullBackupContent="@xml/my_backup_rules"> + </app></pre></li> + <li>Create an XML file called <code>my_backup_rules.xml</code> in the <code>res/xml/</code> directory. Inside the file, add rules with the <code><include></code> and <code><exclude></code> elements. The following sample backs up all shared preferences except <code>device.xml</code>: + <pre><?xml version="1.0" encoding="utf-8"?> +<full-backup-content> + <include domain="sharedpref" path="."/> + <exclude domain="sharedpref" path="device.xml"/> +</full-backup-content></pre></li> + +<h3 id="XMLSyntax">XML Config Syntax</h3> +<p>The XML syntax for the configuration file is shown below: + +<pre class="prettyprint"><full-backup-content> + <include domain=["file" | "database" | "sharedpref" | "external" | "root"] + path="string" /> + <exclude domain=["file" | "database" | "sharedpref" | "external" | "root"] + path="string" /> +</full-backup-content></pre> + +<p>Inside the <code><full-backup-content></code> tag, you can define <code><include></code> and <code><exclude></code> +elements: + +<ul> + <li><code><include></code> - Specifies a file or folder to backup. By default, Auto Backup +includes almost all app files. If you specify an <include> element, the system +no longer includes any files by default and backs up <em>only the files +specified</em>. To include multiple files, use multiple <include> elements. + <p>note: Files in directories returned by <code>getCacheDir()</code>, <code>getCodeCacheDir()</code>, or +<code>getNoBackupFilesDir()</code> are always excluded even if you try to include them.</li> + + <li><code><exclude></code> - Specifies a file or folder to exclude during backup. Here are +some files that are typically excluded from backup: <ul> + <li>Files that have device specific identifiers, either issued by a server or +generated on the device. For example, <a href="https://developers.google.com/cloud-messaging/android/start">Google Cloud Messaging (GCM)</a> needs to +generate a registration token every time a user installs your app on a new +device. If the old registration token is restored, the app may behave +unexpectedly. + <li>Account credentials or other sensitive information. Consider asking the +user to reauthenticate the first time they launch a restored app rather than +allowing for storage of such information in the backup. + <li>Files related to app debugging, such as <a href="{@docRoot}studio/run/index.html#instant-run">instant run files</a>. To exclude instant run files, add the rule <code><exclude +domain="file" path="instant-run"/></code> + <li>Large files that cause the app to exceed the 25MB backup quota.</li> </ul> + </li> </ul> + +<p class="note"><strong>Note:</strong> If your configuration file specifies both elements, then the +backup contains everything captured by the <code><include></code> elements minus the +resources named in the <code><exclude></code> elements. In other words, +<code><exclude></code> takes precedence. + +<p>Each element must include the following two attributes: +<ul> + <li><code>domain</code> - specifies the location of resource. Valid values for this attribute +include the following: <ul> + <li><code>root</code> - the directory on the filesystem where all private files belonging to +this app are stored. + <li><code>file</code> - directories returned by {@link android.content.Context#getFilesDir()}. + <li><code>database</code> - directories returned by {@link android.content.Context#getDatabasePath(String) getDatabasePath()}. +Databases created with {@link android.database.sqlite.SQLiteOpenHelper} +are stored here. + <li><code>sharedpref</code> - the directory where {@link android.content.SharedPreferences} +are stored. + <li><code>external</code> the directory returned by {@link android.content.Context#getExternalFilesDir(String) getExternalFilesDir()} + <p>Note: You cannot backup files outside of these locations.</li></ul> + <li><code>path</code>: Specifies a file or folder to include in or exclude from backup. Note +that: <ul> + <li>This attribute does not support wildcard or regex syntax. + <li>You can use <code>.</code> to reference the current directory, however, you cannot +reference the parent directory <code>..</code> for security reasons. + <li>If you specify a directory, then the rule applies to all files in the +directory and recursive sub-directories.</li></ul></li></ul> + +<h2 id="ImplementingBackupAgent">Implementing BackupAgent</h2> +<p>Apps that implement Auto Backup do not need to implement {@link android.app.backup.BackupAgent}. However, you can optionally implement a custom {@link android.app.backup.BackupAgent}. Typically, there are two reasons for doing this: +<ul> + <li>You want to receive notification of backup events such as, +{@link android.app.backup.BackupAgent#onRestoreFinished()} or {@link android.app.backup.BackupAgent#onQuotaExceeded(long,long)}. These callback methods are executed +even if the app is not running. +<li>You can't easily express the set of files you want to backup with XML rules. +In these very rare cases, you can implement a BackupAgent that overrides {@link android.app.backup.BackupAgent#onFullBackup(FullBackupDataOutput)} to +store what you want. To retain the system's default implementation, call the +corresponding method on the superclass with <code>super.onFullBackup()</code>.</li></ul> + +<p class="note"><strong>Note:</strong> Your <code>BackupAgent</code> must +implement the abstract methods +{@link android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) onBackup()} +and {@link android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) onRestore()}. +Those methods are used for Key/Value Backup. So if +you are not using Key/Value Backup, implement those methods and leave them blank. + +<p>For more information, see +<a href="{@docRoot}guide/topics/data/keyvaluebackup.html#BackupAgent">Extending +BackupAgent</a>.
\ No newline at end of file diff --git a/docs/html/guide/topics/data/backup.jd b/docs/html/guide/topics/data/backup.jd index 619c79021870..a688c6e9889b 100644 --- a/docs/html/guide/topics/data/backup.jd +++ b/docs/html/guide/topics/data/backup.jd @@ -1,930 +1,34 @@ -page.title=Data Backup -@jd:body - - -<div id="qv-wrapper"> -<div id="qv"> - - <h2>Quickview</h2> - <ul> - <li>Back up the user's data to the cloud in case the user loses it</li> - <li>If the user upgrades to a new Android-powered device, your app can restore the user's -data onto the new device</li> - <li>Easily back up SharedPreferences and private files with BackupAgentHelper</li> - <li>Requires API Level 8</li> - </ul> - - <h2>In this document</h2> - <ol> - <li><a href="#Basics">The Basics</a></li> - <li><a href="#BackupManifest">Declaring the Backup Agent in Your Manifest</a></li> - <li><a href="#BackupKey">Registering for Android Backup Service</a></li> - <li><a href="#BackupAgent">Extending BackupAgent</a> - <ol> - <li><a href="#RequiredMethods">Required Methods</a></li> - <li><a href="#PerformingBackup">Performing backup</a></li> - <li><a href="#PerformingRestore">Performing restore</a></li> - </ol> - </li> - <li><a href="#BackupAgentHelper">Extending BackupAgentHelper</a> - <ol> - <li><a href="#SharedPreferences">Backing up SharedPreferences</a></li> - <li><a href="#Files">Backing up Private Files</a></li> - </ol> - </li> - <li><a href="#RestoreVersion">Checking the Restore Data Version</a></li> - <li><a href="#RequestingBackup">Requesting Backup</a></li> - <li><a href="#RequestingRestore">Requesting Restore</a></li> - <li><a href="#Testing">Testing Your Backup Agent</a></li> - </ol> - - <h2>Key classes</h2> - <ol> - <li>{@link android.app.backup.BackupManager}</li> - <li>{@link android.app.backup.BackupAgent}</li> - <li>{@link android.app.backup.BackupAgentHelper}</li> - </ol> - - <h2>See also</h2> - <ol> - <li><a href="{@docRoot}tools/help/bmgr.html">{@code bmgr} tool</a></li> - </ol> - -</div> -</div> - -<p>Android's {@link android.app.backup backup} service allows you to copy your persistent -application data to remote "cloud" storage, in order to provide a restore point for the -application data and settings. If a user performs a factory reset or converts to a new -Android-powered device, the system automatically restores your backup data when the application -is re-installed. This way, your users don't need to reproduce their previous data or -application settings. This process is completely transparent to the user and does not affect the -functionality or user experience in your application.</p> - -<p>During a backup operation (which your application can request), Android's Backup Manager ({@link -android.app.backup.BackupManager}) queries your application for backup data, then hands it to -a backup transport, which then delivers the data to the cloud storage. During a -restore operation, the Backup Manager retrieves the backup data from the backup transport and -returns it to your application so your application can restore the data to the device. It's -possible for your application to request a restore, but that shouldn't be necessary—Android -automatically performs a restore operation when your application is installed and there exists -backup data associated with the user. The primary scenario in which backup data is restored is when -a user resets their device or upgrades to a new device and their previously installed -applications are re-installed.</p> - -<p class="note"><strong>Note:</strong> The backup service is <em>not</em> designed for -synchronizing application data with other clients or saving data that you'd like to access during -the normal application lifecycle. You cannot read or write backup data on demand and cannot access -it in any way other than through the APIs provided by the Backup Manager.</p> - -<p>The backup transport is the client-side component of Android's backup framework, which is -customizable by -the device manufacturer and service provider. The backup transport may differ from device to device -and which backup transport is available on any given device is transparent to your application. The -Backup Manager APIs isolate your application from the actual backup transport available on a given -device—your application communicates with the Backup Manager through a fixed set of APIs, -regardless of the underlying transport.</p> - -<p>Data backup is <em>not</em> guaranteed to be available on all Android-powered -devices. However, your application is not adversely affected in the event -that a device does not provide a backup transport. If you believe that users will benefit from data -backup in your application, then you can implement it as described in this document, test it, then -publish your application without any concern about which devices actually perform backup. When your -application runs on a device that does not provide a backup transport, your application operates -normally, but will not receive callbacks from the Backup Manager to backup data.</p> - -<p>Although you cannot know what the current transport is, you are always assured that your -backup data cannot be read by other applications on the device. Only the Backup Manager and backup -transport have access to the data you provide during a backup operation.</p> - -<p class="caution"><strong>Caution:</strong> Because the cloud storage and transport service can -differ from device to device, Android makes no guarantees about the security of your data while -using backup. You should always be cautious about using backup to store sensitive data, such as -usernames and passwords.</p> - - -<h2 id="Basics">The Basics</h2> - -<p>To backup your application data, you need to implement a backup agent. Your backup -agent is called by the Backup Manager to provide the data you want to back up. It is also called -to restore your backup data when the application is re-installed. The Backup Manager handles all -your data transactions with the cloud storage (using the backup transport) and your backup agent -handles all your data transactions on the device.</p> - -<p>To implement a backup agent, you must:</p> - -<ol> - <li>Declare your backup agent in your manifest file with the <a -href="{@docRoot}guide/topics/manifest/application-element.html#agent">{@code -android:backupAgent}</a> attribute.</li> - <li>Register your application with a backup service. Google offers <a -href="http://code.google.com/android/backup/index.html">Android Backup Service</a> as a backup -service for most Android-powered devices, which requires that you register your application in -order for it to work. Any other backup services available might also require you to register -in order to store your data on their servers.</li> - <li>Define a backup agent by either:</p> - <ol type="a"> - <li><a href="#BackupAgent">Extending BackupAgent</a> - <p>The {@link android.app.backup.BackupAgent} class provides the central interface with -which your application communicates with the Backup Manager. If you extend this class -directly, you must override {@link -android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) -onBackup()} and {@link -android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) -onRestore()} to handle the backup and restore operations for your data.</p> - <p><em>Or</em></p> - <li><a href="#BackupAgentHelper">Extending BackupAgentHelper</a> - <p>The {@link android.app.backup.BackupAgentHelper} class provides a convenient -wrapper around the {@link android.app.backup.BackupAgent} class, which minimizes the amount of code -you need to write. In your {@link android.app.backup.BackupAgentHelper}, you must use one or more -"helper" objects, which automatically backup and restore certain types of data, so that you do not -need to implement {@link -android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) -onBackup()} and {@link -android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) -onRestore()}.</p> - <p>Android currently provides backup helpers that will backup and restore complete files -from {@link android.content.SharedPreferences} and <a -href="{@docRoot}guide/topics/data/data-storage.html#filesInternal">internal storage</a>.</p> - </li> - </ol> - </li> -</ol> - - - -<h2 id="BackupManifest">Declaring the Backup Agent in Your Manifest</h2> - -<p>This is the easiest step, so once you've decided on the class name for your backup agent, declare -it in your manifest with the <a -href="{@docRoot}guide/topics/manifest/application-element.html#agent">{@code -android:backupAgent}</a> attribute in the <a -href="{@docRoot}guide/topics/manifest/application-element.html">{@code -<application>}</a> tag.</p> - -<p>For example:</p> - -<pre> -<manifest ... > - ... - <application android:label="MyApplication" - <b>android:backupAgent="MyBackupAgent"</b>> - <activity ... > - ... - </activity> - </application> -</manifest> -</pre> - -<p>Another attribute you might want to use is <a -href="{@docRoot}guide/topics/manifest/application-element.html#restoreany">{@code -android:restoreAnyVersion}</a>. This attribute takes a boolean value to indicate whether you -want to restore the application data regardless of the current application version compared to the -version that produced the backup data. (The default value is "{@code false}".) See <a -href="#RestoreVersion">Checking the Restore Data Version</a> for more information.</p> - -<p class="note"><strong>Note:</strong> The backup service and the APIs you must use are -available only on devices running API Level 8 (Android 2.2) or greater, so you should also -set your <a -href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code android:minSdkVersion}</a> -attribute to "8".</p> - - - - -<h2 id="BackupKey">Registering for Android Backup Service</h2> - -<p>Google provides a backup transport with <a -href="http://code.google.com/android/backup/index.html">Android Backup Service</a> for most -Android-powered devices running Android 2.2 or greater.</p> - -<p>In order for your application to perform backup using Android Backup Service, you must -register your application with the service to receive a Backup Service Key, then -declare the Backup Service Key in your Android manifest.</p> - -<p>To get your Backup Service Key, <a -href="http://code.google.com/android/backup/signup.html">register for Android Backup Service</a>. -When you register, you will be provided a Backup Service Key and the appropriate {@code -<meta-data>} XML code for your Android manifest file, which you must include as a child of the -{@code <application>} element. For example:</p> - -<pre> -<application android:label="MyApplication" - android:backupAgent="MyBackupAgent"> - ... - <meta-data android:name="com.google.android.backup.api_key" - android:value="AEdPqrEAAAAIDaYEVgU6DJnyJdBmU7KLH3kszDXLv_4DIsEIyQ" /> -</application> -</pre> - -<p>The <code>android:name</code> must be <code>"com.google.android.backup.api_key"</code> and -the <code>android:value</code> must be the Backup Service Key received from the Android Backup -Service registration.</p> - -<p>If you have multiple applications, you must register each one, using the respective package -name.</p> - -<p class="note"><strong>Note:</strong> The backup transport provided by Android Backup Service is -not guaranteed to be available -on all Android-powered devices that support backup. Some devices might support backup -using a different transport, some devices might not support backup at all, and there is no way for -your application to know what transport is used on the device. However, if you implement backup for -your application, you should always include a Backup Service Key for Android Backup Service so -your application can perform backup when the device uses the Android Backup Service transport. If -the device does not use Android Backup Service, then the {@code <meta-data>} element with the -Backup Service Key is ignored.</p> - - - - -<h2 id="BackupAgent">Extending BackupAgent</h2> - -<p>Most applications shouldn't need to extend the {@link android.app.backup.BackupAgent} class -directly, but should instead <a href="#BackupAgentHelper">extend BackupAgentHelper</a> to take -advantage of the built-in helper classes that automatically backup and restore your files. However, -you might want to extend {@link android.app.backup.BackupAgent} directly if you need to:</p> -<ul> - <li>Version your data format. For instance, if you anticipate the need to revise the -format in which you write your application data, you can build a backup agent to cross-check your -application version during a restore operation and perform any necessary compatibility work if the -version on the device is different than that of the backup data. For more information, see <a -href="#RestoreVersion">Checking the Restore Data Version</a>.</li> - <li>Instead of backing up an entire file, you can specify the portions of data the should be -backed up and how each portion is then restored to the device. (This can also help you manage -different versions, because you read and write your data as unique entities, rather than -complete files.)</li> - <li>Back up data in a database. If you have an SQLite database that you want to restore when -the user re-installs your application, you need to build a custom {@link -android.app.backup.BackupAgent} that reads the appropriate data during a backup operation, then -create your table and insert the data during a restore operation.</li> -</ul> - -<p>If you don't need to perform any of the tasks above and want to back up complete files from -{@link android.content.SharedPreferences} or <a -href="{@docRoot}guide/topics/data/data-storage.html#filesInternal">internal storage</a>, you -should skip to <a href="#BackupAgentHelper">Extending BackupAgentHelper</a>.</p> - - - -<h3 id="RequiredMethods">Required Methods</h3> - -<p>When you create a backup agent by extending {@link android.app.backup.BackupAgent}, you -must implement the following callback methods:</p> - -<dl> - <dt>{@link -android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) -onBackup()}</dt> - <dd>The Backup Manager calls this method after you <a href="#RequestingBackup">request a -backup</a>. In this method, you read your application data from the device and pass the data you -want to back up to the Backup Manager, as described below in <a href="#PerformingBackup">Performing -backup</a>.</dd> - - <dt>{@link -android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) -onRestore()}</dt> - <dd>The Backup Manager calls this method during a restore operation (you can <a -href="#RequestingRestore">request a restore</a>, but the system automatically performs restore when -the user re-installs your application). When it calls this method, the Backup Manager delivers your -backup data, which you then restore to the device, as described below in <a -href="#PerformingRestore">Performing restore</a>.</dd> -</dl> - - - -<h3 id="PerformingBackup">Performing backup</h3> - - -<p>When it's time to back up your application data, the Backup Manager calls your {@link -android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) -onBackup()} method. This is where you must provide your application data to the Backup Manager so -it can be saved to cloud storage.</p> - -<p>Only the Backup Manager can call your backup agent's {@link -android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) -onBackup()} method. Each time that your application data changes and you want to perform a backup, -you must request a backup operation by calling {@link -android.app.backup.BackupManager#dataChanged()} (see <a href="#RequestingBackup">Requesting -Backup</a> for more information). A backup request does not result in an immediate call to your -{@link -android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) -onBackup()} method. Instead, the Backup Manager waits for an appropriate time, then performs -backup for all applications that have requested a backup since the last backup was performed.</p> - -<p class="note"><strong>Tip:</strong> While developing your application, you can initiate an -immediate backup operation from the Backup Manager with the <a -href="{@docRoot}tools/help/bmgr.html">{@code bmgr} tool</a>.</p> - -<p>When the Backup Manager calls your {@link -android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) -onBackup()} method, it passes three parameters:</p> - -<dl> - <dt>{@code oldState}</dt> - <dd>An open, read-only {@link android.os.ParcelFileDescriptor} pointing to the last backup -state provided by your application. This is not the backup data from cloud storage, but a -local representation of the data that was backed up the last time {@link -android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) -onBackup()} was called (as defined by {@code newState}, below, or from {@link -android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) -onRestore()}—more about this in the next section). Because {@link -android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) -onBackup()} does not allow you to read existing backup data in -the cloud storage, you can use this local representation to determine whether your data has changed -since the last backup.</dd> - <dt>{@code data}</dt> - <dd>A {@link android.app.backup.BackupDataOutput} object, which you use to deliver your backup -data to the Backup Manager.</dd> - <dt>{@code newState}</dt> - <dd>An open, read/write {@link android.os.ParcelFileDescriptor} pointing to a file in which -you must write a representation of the data that you delivered to {@code data} (a representation -can be as simple as the last-modified timestamp for your file). This object is -returned as {@code oldState} the next time the Backup Manager calls your {@link -android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) -onBackup()} method. If you do not write your backup data to {@code newState}, then {@code oldState} -will point to an empty file next time Backup Manager calls {@link -android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) -onBackup()}.</dd> -</dl> - -<p>Using these parameters, you should implement your {@link -android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) -onBackup()} method to do the following:</p> - -<ol> - <li>Check whether your data has changed since the last backup by comparing {@code oldState} to -your current data. How you read data in {@code oldState} depends on how you originally wrote it to -{@code newState} (see step 3). The easiest way to record the state of a file is with its -last-modified timestamp. For example, here's how you can read and compare a timestamp from {@code -oldState}: - <pre> -// Get the oldState input stream -FileInputStream instream = new FileInputStream(oldState.getFileDescriptor()); -DataInputStream in = new DataInputStream(instream); - -try { - // Get the last modified timestamp from the state file and data file - long stateModified = in.readLong(); - long fileModified = mDataFile.lastModified(); - - if (stateModified != fileModified) { - // The file has been modified, so do a backup - // Or the time on the device changed, so be safe and do a backup - } else { - // Don't back up because the file hasn't changed - return; - } -} catch (IOException e) { - // Unable to read state file... be safe and do a backup -} -</pre> - <p>If nothing has changed and you don't need to back up, skip to step 3.</p> - </li> - <li>If your data has changed, compared to {@code oldState}, write the current data to -{@code data} to back it up to the cloud storage. - <p>You must write each chunk of data as an "entity" in the {@link -android.app.backup.BackupDataOutput}. An entity is a flattened binary data -record that is identified by a unique key string. Thus, the data set that you back up is -conceptually a set of key-value pairs.</p> - <p>To add an entity to your backup data set, you must:</p> - <ol> - <li>Call {@link android.app.backup.BackupDataOutput#writeEntityHeader(String,int) -writeEntityHeader()}, passing a unique string key for the data you're about to write and the data -size.</li> - <li>Call {@link android.app.backup.BackupDataOutput#writeEntityData(byte[],int) -writeEntityData()}, passing a byte buffer that contains your data and the number of bytes to write -from the buffer (which should match the size passed to {@link -android.app.backup.BackupDataOutput#writeEntityHeader(String,int) writeEntityHeader()}).</li> - </ol> - <p>For example, the following code flattens some data into a byte stream and writes it into a -single entity:</p> - <pre> -// Create buffer stream and data output stream for our data -ByteArrayOutputStream bufStream = new ByteArrayOutputStream(); -DataOutputStream outWriter = new DataOutputStream(bufStream); -// Write structured data -outWriter.writeUTF(mPlayerName); -outWriter.writeInt(mPlayerScore); -// Send the data to the Backup Manager via the BackupDataOutput -byte[] buffer = bufStream.toByteArray(); -int len = buffer.length; -data.writeEntityHeader(TOPSCORE_BACKUP_KEY, len); -data.writeEntityData(buffer, len); -</pre> - <p>Perform this for each piece of data that you want to back up. How you divide your data into -entities is up to you (and you might use just one entity).</p> - </li> - <li>Whether or not you perform a backup (in step 2), write a representation of the current data to -the {@code newState} {@link android.os.ParcelFileDescriptor}. The Backup Manager retains this object -locally as a representation of the data that is currently backed up. It passes this back to you as -{@code oldState} the next time it calls {@link -android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) -onBackup()} so you can determine whether another backup is necessary (as handled in step 1). If you -do not write the current data state to this file, then -{@code oldState} will be empty during the next callback. - <p>The following example saves a representation of the current data into {@code newState} using -the file's last-modified timestamp:</p> - <pre> -FileOutputStream outstream = new FileOutputStream(newState.getFileDescriptor()); -DataOutputStream out = new DataOutputStream(outstream); - -long modified = mDataFile.lastModified(); -out.writeLong(modified); -</pre> - </li> -</ol> - -<p class="caution"><strong>Caution:</strong> If your application data is saved to a file, make sure -that you use synchronized statements while accessing the file so that your backup agent does not -read the file while an Activity in your application is also writing the file.</p> - - - - -<h3 id="PerformingRestore">Performing restore</h3> - -<p>When it's time to restore your application data, the Backup Manager calls your backup -agent's {@link android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) -onRestore()} method. When it calls this method, the Backup Manager delivers your backup data so -you can restore it onto the device.</p> - -<p>Only the Backup Manager can call {@link -android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) -onRestore()}, which happens automatically when the system installs your application and -finds existing backup data. However, you can request a restore operation for -your application by calling {@link -android.app.backup.BackupManager#requestRestore(RestoreObserver) requestRestore()} (see <a -href="#RequestingRestore">Requesting restore</a> for more information).</p> - -<p class="note"><strong>Note:</strong> While developing your application, you can also request a -restore operation with the <a href="{@docRoot}tools/help/bmgr.html">{@code bmgr} -tool</a>.</p> - -<p>When the Backup Manager calls your {@link -android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) -onRestore()} method, it passes three parameters:</p> - -<dl> - <dt>{@code data}</dt> - <dd>A {@link android.app.backup.BackupDataInput}, which allows you to read your backup -data.</dd> - <dt>{@code appVersionCode}</dt> - <dd>An integer representing the value of your application's <a -href="{@docRoot}guide/topics/manifest/manifest-element.html#vcode">{@code android:versionCode}</a> -manifest attribute, as it was when this data was backed up. You can use this to cross-check the -current application version and determine if the data format is compatible. For more -information about using this to handle different versions of restore data, see the section -below about <a href="#RestoreVersion">Checking the Restore Data Version</a>.</dd> - <dt>{@code newState}</dt> - <dd>An open, read/write {@link android.os.ParcelFileDescriptor} pointing to a file in which -you must write the final backup state that was provided with {@code data}. This object is -returned as {@code oldState} the next time {@link -android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) -onBackup()} is called. Recall that you must also write the same {@code newState} object in the -{@link -android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) -onBackup()} callback—also doing it here ensures that the {@code oldState} object given to -{@link -android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) -onBackup()} is valid even the first time {@link -android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) -onBackup()} is called after the device is restored.</dd> -</dl> - -<p>In your implementation of {@link -android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) -onRestore()}, you should call {@link android.app.backup.BackupDataInput#readNextHeader()} on the -{@code data} to iterate -through all entities in the data set. For each entity found, do the following:</p> - -<ol> - <li>Get the entity key with {@link android.app.backup.BackupDataInput#getKey()}.</li> - <li>Compare the entity key to a list of known key values that you should have declared as static -final strings inside your {@link android.app.backup.BackupAgent} class. When the key matches one of -your known key strings, enter into a statement to extract the entity data and save it to the device: - <ol> - <li>Get the entity data size with {@link -android.app.backup.BackupDataInput#getDataSize()} and create a byte array of that size.</li> - <li>Call {@link android.app.backup.BackupDataInput#readEntityData(byte[],int,int) -readEntityData()} and pass it the byte array, which is where the data will go, and specify the -start offset and the size to read.</li> - <li>Your byte array is now full and you can read the data and write it to the device -however you like.</li> - </ol> - </li> - <li>After you read and write your data back to the device, write the state of your data to the -{@code newState} parameter the same as you do during {@link -android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) -onBackup()}. -</ol> +page.title=Backing up App Data to the Cloud +page.tags=cloud,sync,backup -<p>For example, here's how you can restore the data backed up by the example in the previous -section:</p> - -<pre> -@Override -public void onRestore(BackupDataInput data, int appVersionCode, - ParcelFileDescriptor newState) throws IOException { - // There should be only one entity, but the safest - // way to consume it is using a while loop - while (data.readNextHeader()) { - String key = data.getKey(); - int dataSize = data.getDataSize(); - - // If the key is ours (for saving top score). Note this key was used when - // we wrote the backup entity header - if (TOPSCORE_BACKUP_KEY.equals(key)) { - // Create an input stream for the BackupDataInput - byte[] dataBuf = new byte[dataSize]; - data.readEntityData(dataBuf, 0, dataSize); - ByteArrayInputStream baStream = new ByteArrayInputStream(dataBuf); - DataInputStream in = new DataInputStream(baStream); - - // Read the player name and score from the backup data - mPlayerName = in.readUTF(); - mPlayerScore = in.readInt(); - - // Record the score on the device (to a file or something) - recordScore(mPlayerName, mPlayerScore); - } else { - // We don't know this entity key. Skip it. (Shouldn't happen.) - data.skipEntityData(); - } - } - - // Finally, write to the state blob (newState) that describes the restored data - FileOutputStream outstream = new FileOutputStream(newState.getFileDescriptor()); - DataOutputStream out = new DataOutputStream(outstream); - out.writeUTF(mPlayerName); - out.writeInt(mPlayerScore); -} -</pre> - -<p>In this example, the {@code appVersionCode} parameter passed to {@link -android.app.backup.BackupAgent#onRestore onRestore()} is not used. However, you might want to use -it if you've chosen to perform backup when the user's version of the application has actually moved -backward (for example, the user went from version 1.5 of your app to 1.0). For more information, see -the section about <a href="#RestoreVersion">Checking the Restore Data Version</a>.</p> - -<div class="special"> -<p>For an example implementation of {@link android.app.backup.BackupAgent}, see the <a -href="{@docRoot}resources/samples/BackupRestore/src/com/example/android/backuprestore/ExampleAgent.html">{@code -ExampleAgent}</a> class in the <a -href="{@docRoot}resources/samples/BackupRestore/index.html">Backup and Restore</a> sample -application.</p> -</div> - - - - - - -<h2 id="BackupAgentHelper">Extending BackupAgentHelper</h2> - -<p>You should build your backup agent using {@link android.app.backup.BackupAgentHelper} if you want -to back up complete files (from either {@link android.content.SharedPreferences} or <a -href="{@docRoot}guide/topics/data/data-storage.html#filesInternal">internal storage</a>). -Building your backup agent with {@link android.app.backup.BackupAgentHelper} requires far less -code than extending {@link android.app.backup.BackupAgent}, because you don't have to implement -{@link -android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) -onBackup()} and {@link -android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) -onRestore()}.</p> - -<p>Your implementation of {@link android.app.backup.BackupAgentHelper} must -use one or more backup helpers. A backup helper is a specialized -component that {@link android.app.backup.BackupAgentHelper} summons to perform backup and -restore operations for a particular type of data. The Android framework currently provides two -different helpers:</p> -<ul> - <li>{@link android.app.backup.SharedPreferencesBackupHelper} to backup {@link -android.content.SharedPreferences} files.</li> - <li>{@link android.app.backup.FileBackupHelper} to backup files from <a -href="{@docRoot}guide/topics/data/data-storage.html#filesInternal">internal storage</a>.</li> -</ul> - -<p>You can include multiple helpers in your {@link android.app.backup.BackupAgentHelper}, but only -one helper is needed for each data type. That is, if you have multiple {@link -android.content.SharedPreferences} files, then you need only one {@link -android.app.backup.SharedPreferencesBackupHelper}.</p> - -<p>For each helper you want to add to your {@link android.app.backup.BackupAgentHelper}, you must do -the following during your {@link android.app.backup.BackupAgent#onCreate()} method:</p> -<ol> - <li>Instantiate in instance of the desired helper class. In the class constructor, you must -specify the appropriate file(s) you want to backup.</li> - <li>Call {@link android.app.backup.BackupAgentHelper#addHelper(String,BackupHelper) addHelper()} -to add the helper to your {@link android.app.backup.BackupAgentHelper}.</li> -</ol> - -<p>The following sections describe how to create a backup agent using each of the available -helpers.</p> - - - -<h3 id="SharedPreferences">Backing up SharedPreferences</h3> - -<p>When you instantiate a {@link android.app.backup.SharedPreferencesBackupHelper}, you must -include the name of one or more {@link android.content.SharedPreferences} files.</p> - -<p>For example, to back up a {@link android.content.SharedPreferences} file named -"user_preferences", a complete backup agent using {@link android.app.backup.BackupAgentHelper} looks -like this:</p> - -<pre> -public class MyPrefsBackupAgent extends BackupAgentHelper { - // The name of the SharedPreferences file - static final String PREFS = "user_preferences"; - - // A key to uniquely identify the set of backup data - static final String PREFS_BACKUP_KEY = "prefs"; - - // Allocate a helper and add it to the backup agent - @Override - public void onCreate() { - SharedPreferencesBackupHelper helper = - new SharedPreferencesBackupHelper(this, PREFS); - addHelper(PREFS_BACKUP_KEY, helper); - } -} -</pre> - -<p>That's it! That's your entire backup agent. The {@link -android.app.backup.SharedPreferencesBackupHelper} includes all the code -needed to backup and restore a {@link android.content.SharedPreferences} file.</p> - -<p>When the Backup Manager calls {@link -android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) -onBackup()} and {@link -android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) -onRestore()}, {@link android.app.backup.BackupAgentHelper} calls your backup helpers to perform -backup and restore for your specified files.</p> - -<p class="note"><strong>Note:</strong> {@link android.content.SharedPreferences} are threadsafe, so -you can safely read and write the shared preferences file from your backup agent and -other activities.</p> - - - -<h3 id="Files">Backing up other files</h3> - -<p>When you instantiate a {@link android.app.backup.FileBackupHelper}, you must include the name of -one or more files that are saved to your application's <a -href="{@docRoot}guide/topics/data/data-storage.html#filesInternal">internal storage</a> -(as specified by {@link android.content.ContextWrapper#getFilesDir()}, which is the same -location where {@link android.content.Context#openFileOutput(String,int) openFileOutput()} writes -files).</p> - -<p>For example, to backup two files named "scores" and "stats," a backup agent using {@link -android.app.backup.BackupAgentHelper} looks like this:</p> - -<pre> -public class MyFileBackupAgent extends BackupAgentHelper { - // The name of the file - static final String TOP_SCORES = "scores"; - static final String PLAYER_STATS = "stats"; - - // A key to uniquely identify the set of backup data - static final String FILES_BACKUP_KEY = "myfiles"; - - // Allocate a helper and add it to the backup agent - @Override - public void onCreate() { - FileBackupHelper helper = new FileBackupHelper(this, - TOP_SCORES, PLAYER_STATS); - addHelper(FILES_BACKUP_KEY, helper); - } -} -</pre> - -<p>The {@link android.app.backup.FileBackupHelper} includes all the code necessary to backup and -restore files that are saved to your application's <a -href="{@docRoot}guide/topics/data/data-storage.html#filesInternal">internal storage</a>..</p> - -<p>However, reading and writing to files on internal storage is <strong>not threadsafe</strong>. To -ensure that your backup agent does not read or write your files at the same time as your activities, -you must use synchronized statements each time you perform a read or write. For example, -in any Activity where you read and write the file, you need an object to use as the intrinsic -lock for the synchronized statements:</p> - -<pre> -// Object for intrinsic lock -static final Object sDataLock = new Object(); -</pre> - -<p>Then create a synchronized statement with this lock each time you read or write the files. For -example, here's a synchronized statement for writing the latest score in a game to a file:</p> - -<pre> -try { - synchronized (MyActivity.sDataLock) { - File dataFile = new File({@link android.content.Context#getFilesDir()}, TOP_SCORES); - RandomAccessFile raFile = new RandomAccessFile(dataFile, "rw"); - raFile.writeInt(score); - } -} catch (IOException e) { - Log.e(TAG, "Unable to write to file"); -} -</pre> - -<p>You should synchronize your read statements with the same lock.</p> - -<p>Then, in your {@link android.app.backup.BackupAgentHelper}, you must override {@link -android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) -onBackup()} and {@link -android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) -onRestore()} to synchronize the backup and restore operations with the same -intrinsic lock. For example, the {@code MyFileBackupAgent} example from above needs the following -methods:</p> - -<pre> -@Override -public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data, - ParcelFileDescriptor newState) throws IOException { - // Hold the lock while the FileBackupHelper performs backup - synchronized (MyActivity.sDataLock) { - super.onBackup(oldState, data, newState); - } -} - -@Override -public void onRestore(BackupDataInput data, int appVersionCode, - ParcelFileDescriptor newState) throws IOException { - // Hold the lock while the FileBackupHelper restores the file - synchronized (MyActivity.sDataLock) { - super.onRestore(data, appVersionCode, newState); - } -} -</pre> - -<p>That's it. All you need to do is add your {@link android.app.backup.FileBackupHelper} in the -{@link android.app.backup.BackupAgent#onCreate()} method and override {@link -android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) -onBackup()} and {@link -android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) -onRestore()} to synchronize read and write operations.</p> - -<div class="special"> -<p>For an example implementation of {@link -android.app.backup.BackupAgentHelper} with {@link android.app.backup.FileBackupHelper}, see the -{@code FileHelperExampleAgent} class in the <a -href="{@docRoot}resources/samples/BackupRestore/index.html">Backup and Restore</a> sample -application.</p> -</div> - - - - - - -<h2 id="RestoreVersion">Checking the Restore Data Version</h2> - -<p>When the Backup Manager saves your data to cloud storage, it automatically includes the version -of your application, as defined by your manifest file's <a -href="{@docRoot}guide/topics/manifest/manifest-element.html#vcode">{@code android:versionCode}</a> -attribute. Before the Backup Manager calls your backup agent to restore your data, it -looks at the <a -href="{@docRoot}guide/topics/manifest/manifest-element.html#vcode">{@code -android:versionCode}</a> of the installed application and compares it to the value -recorded in the restore data set. If the version recorded in the restore data set is -<em>newer</em> than the application version on the device, then the user has downgraded their -application. In this case, the Backup Manager will abort the restore operation for your application -and not call your {@link -android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) onRestore()} -method, because the restore set is considered meaningless to an older version.</p> - -<p>You can override this behavior with the <a -href="{@docRoot}guide/topics/manifest/application-element.html#restoreany">{@code -android:restoreAnyVersion}</a> attribute. This attribute is either "{@code true}" or "{@code -false}" to indicate whether you want to restore the application regardless of the restore set -version. The default value is "{@code false}". If you define this to be "{@code true}" then the -Backup Manager will ignore the <a -href="{@docRoot}guide/topics/manifest/manifest-element.html#vcode">{@code android:versionCode}</a> -and call your {@link -android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) onRestore()} -method in all cases. In doing so, you can manually check for the version difference in your {@link -android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) onRestore()} -method and take any steps necessary to make the data compatible if the versions conflict.</p> - -<p>To help you handle different versions during a restore operation, the {@link -android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) onRestore()} -method passes you the version code included with the restore data set as the {@code appVersionCode} -parameter. You can then query the current application's version code with the {@link -android.content.pm.PackageInfo#versionCode PackageInfo.versionCode} field. For example:</p> - -<pre> -PackageInfo info; -try { - String name = {@link android.content.ContextWrapper#getPackageName() getPackageName}(); - info = {@link android.content.ContextWrapper#getPackageManager -getPackageManager}().{@link android.content.pm.PackageManager#getPackageInfo(String,int) -getPackageInfo}(name,0); -} catch (NameNotFoundException nnfe) { - info = null; -} - -int version; -if (info != null) { - version = info.versionCode; -} -</pre> - -<p>Then simply compare the {@code version} acquired from {@link android.content.pm.PackageInfo} -to the {@code appVersionCode} passed into {@link -android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) onRestore()}. -</p> - -<p class="caution"><strong>Caution:</strong> Be certain you understand the consequences of setting -<a href="{@docRoot}guide/topics/manifest/application-element.html#restoreany">{@code -android:restoreAnyVersion}</a> to "{@code true}" for your application. If each version of your -application that supports backup does not properly account for variations in your data format during -{@link -android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) onRestore()}, -then the data on the device could be saved in a format incompatible with the version currently -installed on the device.</p> - - - -<h2 id="RequestingBackup">Requesting Backup</h2> - -<p>You can request a backup operation at any time by calling {@link -android.app.backup.BackupManager#dataChanged()}. This method notifies the Backup Manager that you'd -like to backup your data using your backup agent. The Backup Manager then calls your backup -agent's {@link -android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) -onBackup()} method at an opportune time in the future. Typically, you should -request a backup each time your data changes (such as when the user changes an application -preference that you'd like to back up). If you call {@link -android.app.backup.BackupManager#dataChanged()} several times consecutively, before the Backup -Manager requests a backup from your agent, your agent still receives just one call to {@link -android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) -onBackup()}.</p> - -<p class="note"><strong>Note:</strong> While developing your application, you can request a -backup and initiate an immediate backup operation with the <a -href="{@docRoot}tools/help/bmgr.html">{@code bmgr} -tool</a>.</p> - - -<h2 id="RequestingRestore">Requesting Restore</h2> - -<p>During the normal life of your application, you shouldn't need to request a restore operation. -They system automatically checks for backup data and performs a restore when your application is -installed. However, you can manually request a restore operation by calling {@link -android.app.backup.BackupManager#requestRestore(RestoreObserver) requestRestore()}, if necessary. In -which case, the Backup Manager calls your {@link -android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) onRestore()} -implementation, passing the data from the current set of backup data.</p> - -<p class="note"><strong>Note:</strong> While developing your application, you can request a -restore operation with the <a href="{@docRoot}tools/help/bmgr.html">{@code bmgr} -tool</a>.</p> - - -<h2 id="Testing">Testing Your Backup Agent</h2> - -<p>Once you've implemented your backup agent, you can test the backup and restore functionality -with the following procedure, using <a -href="{@docRoot}tools/help/bmgr.html">{@code bmgr}</a>.</p> - -<ol> - <li>Install your application on a suitable Android system image - <ul> - <li>If using the emulator, create and use an AVD with Android 2.2 (API Level 8).</li> - <li>If using a device, the device must be running Android 2.2 or greater and have Google -Play built in.</li> - </ul> - </li> - <li>Ensure that backup is enabled - <ul> - <li>If using the emulator, you can enable backup with the following command from your SDK -{@code tools/} path: -<pre class="no-pretty-print">adb shell bmgr enable true</pre> - </li> - <li>If using a device, open the system <b>Settings</b>, select - <b>Backup & reset</b>, then enable - <b>Back up my data</b> and <b>Automatic restore</b>.</li> - </ul> - </li> - <li>Open your application and initialize some data - <p>If you've properly implemented backup in your application, then it should request a -backup each time the data changes. For example, each time the user changes some data, your app -should call {@link android.app.backup.BackupManager#dataChanged()}, which adds a backup request to -the Backup Manager queue. For testing purposes, you can also make a request with the following -{@code bmgr} command:</p> -<pre class="no-pretty-print">adb shell bmgr backup <em>your.package.name</em></pre> - </li> - <li>Initiate a backup operation: -<pre class="no-pretty-print">adb shell bmgr run</pre> - <p>This forces the Backup Manager to perform all backup requests that are in its -queue.</p> - <li>Uninstall your application: -<pre class="no-pretty-print">adb uninstall <em>your.package.name</em></pre> - </li> - <li>Re-install your application.</li> -</ol> - -<p>If your backup agent is successful, all the data you initialized in step 4 is restored.</p> +startpage=true +@jd:body +<p>Users often invest significant time and effort creating data and setting +preferences within apps. Preserving that data for users if they replace a broken +device or upgrade to a new one is an important part of ensuring a great user +experience. This section covers techniques for backing up data to the cloud so +that users can restore their data. + +<p>Android provides two ways for apps to backup their data to the cloud: +<a href="{@docRoot}guide/topics/data/autobackup.html">Auto Backup for Apps</a> and +<a href="{@docRoot}guide/topics/data/keyvaluebackup.html">Key/Value Backup</a>. +Auto Backup, which is available starting API 23, preserves app data by uploading +it to the user’s Google Drive account. The Key/Value Backup feature (formerly +known as the Backup API and the Android Backup Service) preserves app data by +uploading it to the <a href="{@docRoot}google/backup/index.html">Android Backup Service</a>. + +<p>Generally, we recommend Auto Backup because it requires no work to implement. +Apps that target Android 6.0 (API level 23) or higher are automatically enabled +for Auto Backup. The Auto Backup feature does have some limitations in terms of +what data it can backup and it's availability on Android 6.0 and higher devices. +Consider using the Key/Value Backup feature if you have more specific needs for +backing up your app data. For more information, see <a href="{@docRoot}guide/topics/data/keyvaluebackup.html#Comparison">Comparison of Key/Value and Auto Backup</a></p> + +<p class="note"><strong>Note:</strong> These data backup features are not designed for synchronizing app data with other clients or +saving data that you'd like to access during the normal application lifecycle. +You cannot read or write backup data on demand. For synchronizing app data, see +<a href="{@docRoot}training/sync-adapters/index.html">Transferring +Data Using Sync Adapters</a> or <a href="https://developers.google.com/drive/android/">Google Drive Android +API</a>.
\ No newline at end of file diff --git a/docs/html/guide/topics/data/images/backup-framework.png b/docs/html/guide/topics/data/images/backup-framework.png Binary files differnew file mode 100644 index 000000000000..2ba2e612c9bd --- /dev/null +++ b/docs/html/guide/topics/data/images/backup-framework.png diff --git a/docs/html/guide/topics/data/index.jd b/docs/html/guide/topics/data/index.jd index 3872825f1619..2365f18aaeb8 100644 --- a/docs/html/guide/topics/data/index.jd +++ b/docs/html/guide/topics/data/index.jd @@ -5,21 +5,3 @@ page.landing.image= @jd:body -<div class="landing-docs"> - - - <div class="col-12"> - <h3>Training</h3> - - <a href="{@docRoot}training/backup/index.html"> - <h4>Backing up App Data to the Cloud</h4> - <p> - This class covers techniques for backing up data to the cloud so that - users can restore their data when recovering from a data loss (such as a - factory reset) or installing your application on a new device. - </p> - </a> - - </div> - -</div> diff --git a/docs/html/guide/topics/data/keyvaluebackup.jd b/docs/html/guide/topics/data/keyvaluebackup.jd new file mode 100644 index 000000000000..c7c5e2fd0ce1 --- /dev/null +++ b/docs/html/guide/topics/data/keyvaluebackup.jd @@ -0,0 +1,884 @@ +page.title=Key/Value Backup +page.tags=backup, marshmallow, androidm +page.keywords=backup, kvbackup + +@jd:body + +<div id="qv-wrapper"> +<div id="qv"> + <h2>In this document</h2> + <ol> + <li><a href="#Comparison">Comparison to Auto Backup</a></li> + <li><a href="#ImplementingBackup">Implementing Key/Value Backup</a></li> + + <li><a href="#BackupManifest">Declaring the backup agent in your manifest</a></li> + <li><a href="#BackupKey">Registering for Android Backup Service</a></li> + <li><a href="#BackupAgent">Extending BackupAgent</a> + <ol> + <li><a href="#RequiredMethods">Required methods</a></li> + <li><a href="#PerformingBackup">Performing backup</a></li> + <li><a href="#PerformingRestore">Performing restore</a></li> + </ol> + </li> + <li><a href="#BackupAgentHelper">Extending BackupAgentHelper</a> + <ol> + <li><a href="#SharedPreferences">Backing up SharedPreferences</a></li> + <li><a href="#Files">Backing up private files</a></li> + </ol> + </li> + <li><a href="#RestoreVersion">Checking the restore data version</a></li> + <li><a href="#RequestingBackup">Requesting backup</a></li> + <li><a href="#RequestingRestore">Requesting restore</a></li> + <li><a href="#Migrating">Migrating to Auto Backup</a></li> + </ol> + + <h2>Key classes</h2> + <ol> + <li>{@link android.app.backup.BackupManager}</li> + <li>{@link android.app.backup.BackupAgent}</li> + <li>{@link android.app.backup.BackupAgentHelper}</li> + </ol> + +</div> +</div> + + +<p>Since Android 2.2 (API 8), Android has offered the <em>Key/Value Backup</em> +feature as a way for developers to backup app data to the cloud. The Key/Value +Backup feature (formerly known as the Backup API and the Android Backup Service) +preserves app data by uploading it to +<a href="{@docRoot}google/backup/index.html">Android Backup Service</a>. +The amount of data is limited to 5MB per user of your app and there is +no charge for storing backup data. + +<p class="note"><strong>Note:</strong> If your app implements Key/Value Backup +and targets API 23 or higher, you should set +<a href="{@docRoot}reference/android/R.attr.html#fullBackupOnly">android:fullBackupOnly</a>. +This attribute indicates whether or not to use Auto Backup on devices where it is available. + +<h2 id="Comparison">Comparison to Auto Backup</h2> +<p>Like Auto Backup, Key/Value Backups are restored automatically whenever the app +is installed. The following table describes some of the key differences between Key/Value Backup and Auto Backup: + +<table> + <tr> + <th>Key/Value Backup</th> + <th>Auto Backup</th> + </tr> + <tr> + <td>Available in API 8, Android 2.2</td> + <td>Available in API 23, Android 6.0</td> + </tr> + <tr> + <td>Apps must implement a {@link android.app.backup.BackupAgent}. The backup agent defines what data to backup and how to +restore data.</td> + <td>By default, Auto Backup includes almost all of the app's files. You can +use XML to include and exclude files. Under the hood, Auto Backup relies on a +backup agent that is built into the framework.</td> + </tr> + <tr> + <td>Apps must issue a request when there is data +that is ready to be backed up. Requests +from multiple apps are batched and executed every few hours.</td> + <td>Backups happen automatically roughly once a day.</td> + </tr> + <tr> + <td>Backup data can be transmitted via wifi or cellular data.</td> + <td>Backup data is tranmitted only via wifi. If the device is never connected to a +wifi network, then Auto Backup never occurs.</td> + </tr> + <tr> + <td>Apps are not shut down during backup.</td> + <td>The system shuts down the app during backup.</td> + </tr> + <tr> + <td>Backup data is stored in <a href="{@docRoot}google/backup/index.html">Android Backup Service</a> limited to 5MB per app.</td> + <td>Backup data is stored in the user's Google Drive limited to 25MB per app.</td> + </tr> + <tr> + <td>Related API methods are not filed based:<ul> + <li>{@link android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor, BackupDataOutput, ParcelFileDescriptor) onBackup()} + <li>{@link android.app.backup.BackupAgent#onRestore(BackupDataInput, int, ParcelFileDescriptor) onRestore()}</ul></td> + <td>Related API methods are filed based:<ul> +<li>{@link android.app.backup.BackupAgent#onFullBackup(FullBackupDataOutput) onFullBackup()} +<li>{@link android.app.backup.BackupAgent#onRestoreFile(ParcelFileDescriptor,long,File,int,long,long) onRestoreFile()}</ul></td> + </tr> +</table> + +<h2 id="ImplementingBackup">Implementing Key/Value Backup</h2> +<p>To backup your application data, you need to implement a backup agent. Your backup +agent is called by the Backup Manager both during backup and restore.</p> + +<p>To implement a backup agent, you must:</p> + +<ol> + <li>Declare your backup agent in your manifest file with the <a +href="{@docRoot}guide/topics/manifest/application-element.html#agent">{@code +android:backupAgent}</a> attribute.</li> + <li>Register your application with <a href="{@docRoot}google/backup/index.html">Android + Backup Service</a></li> + <li>Define a backup agent by either:</p> + <ol type="a"> + <li><a href="#BackupAgent">Extending BackupAgent</a> + <p>The {@link android.app.backup.BackupAgent} class provides the central interface with +which your application communicates with the Backup Manager. If you extend this class +directly, you must override {@link +android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) +onBackup()} and {@link +android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) +onRestore()} to handle the backup and restore operations for your data.</p> + <p><em>Or</em></p> + <li><a href="#BackupAgentHelper">Extending BackupAgentHelper</a> + <p>The {@link android.app.backup.BackupAgentHelper} class provides a convenient +wrapper around the {@link android.app.backup.BackupAgent} class, which minimizes the amount of code +you need to write. In your {@link android.app.backup.BackupAgentHelper}, you must use one or more +"helper" objects, which automatically backup and restore certain types of data, so that you do not +need to implement {@link +android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) +onBackup()} and {@link +android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) +onRestore()}.</p> + <p>Android currently provides backup helpers that will backup and restore complete files +from {@link android.content.SharedPreferences} and <a +href="{@docRoot}guide/topics/data/data-storage.html#filesInternal">internal storage</a>.</p> + </li> + </ol> + </li> +</ol> + +<h2 id="BackupManifest">Declaring the backup agent in your manifest</h2> + +<p>This is the easiest step, so once you've decided on the class name for your backup agent, declare +it in your manifest with the <a +href="{@docRoot}guide/topics/manifest/application-element.html#agent">{@code +android:backupAgent}</a> attribute in the <a +href="{@docRoot}guide/topics/manifest/application-element.html">{@code +<application>}</a> tag.</p> + +<p>For example:</p> + +<pre> +<manifest ... > + ... + <application android:label="MyApplication" + <b>android:backupAgent="MyBackupAgent"</b>> + <activity ... > + ... + </activity> + </application> +</manifest> +</pre> + +<p>Another attribute you might want to use is <a +href="{@docRoot}guide/topics/manifest/application-element.html#restoreany">{@code +android:restoreAnyVersion}</a>. This attribute takes a boolean value to indicate whether you +want to restore the application data regardless of the current application version compared to the +version that produced the backup data. (The default value is "{@code false}".) See <a +href="#RestoreVersion">Checking the Restore Data Version</a> for more information.</p> + +<p class="note"><strong>Note:</strong> The backup service and the APIs you must use are +available only on devices running API Level 8 (Android 2.2) or greater, so you should also +set your <a +href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code android:minSdkVersion}</a> +attribute to "8".</p> + + + + +<h2 id="BackupKey">Registering for Android Backup Service</h2> + +<p>Google provides a backup transport with <a +href="{@docRoot}google/backup/index.html">Android Backup Service</a> for most +Android-powered devices running Android 2.2 or greater.</p> + +<p>In order for your application to perform backup using Android Backup Service, you must +register your application with the service to receive a Backup Service Key, then +declare the Backup Service Key in your Android manifest.</p> + +<p>To get your Backup Service Key, <a +href="{@docRoot}google/backup/signup.html">register for Android Backup Service</a>. +When you register, you will be provided a Backup Service Key and the appropriate {@code +<meta-data>} XML code for your Android manifest file, which you must include as a child of the +{@code <application>} element. For example:</p> + +<pre> +<application android:label="MyApplication" + android:backupAgent="MyBackupAgent"> + ... + <meta-data android:name="com.google.android.backup.api_key" + android:value="AEdPqrEAAAAIDaYEVgU6DJnyJdBmU7KLH3kszDXLv_4DIsEIyQ" /> +</application> +</pre> + +<p>The <code>android:name</code> must be <code>"com.google.android.backup.api_key"</code> and +the <code>android:value</code> must be the Backup Service Key received from the Android Backup +Service registration.</p> + +<p>If you have multiple applications, you must register each one, using the respective package +name.</p> + +<p class="note"><strong>Note:</strong> The backup transport provided by Android Backup Service is +not guaranteed to be available +on all Android-powered devices that support backup. Some devices might support backup +using a different transport, some devices might not support backup at all, and there is no way for +your application to know what transport is used on the device. However, if you implement backup for +your application, you should always include a Backup Service Key for Android Backup Service so +your application can perform backup when the device uses the Android Backup Service transport. If +the device does not use Android Backup Service, then the {@code <meta-data>} element with the +Backup Service Key is ignored.</p> + + + + +<h2 id="BackupAgent">Extending BackupAgent</h2> + +<p>Most applications shouldn't need to extend the {@link android.app.backup.BackupAgent} class +directly, but should instead <a href="#BackupAgentHelper">extend BackupAgentHelper</a> to take +advantage of the built-in helper classes that automatically backup and restore your files. However, +you might want to extend {@link android.app.backup.BackupAgent} directly if you need to:</p> +<ul> + <li>Version your data format. For instance, if you anticipate the need to revise the +format in which you write your application data, you can build a backup agent to cross-check your +application version during a restore operation and perform any necessary compatibility work if the +version on the device is different than that of the backup data. For more information, see <a +href="#RestoreVersion">Checking the Restore Data Version</a>.</li> + <li>Instead of backing up an entire file, you can specify the portions of data the should be +backed up and how each portion is then restored to the device. (This can also help you manage +different versions, because you read and write your data as unique entities, rather than +complete files.)</li> + <li>Back up data in a database. If you have an SQLite database that you want to restore when +the user re-installs your application, you need to build a custom {@link +android.app.backup.BackupAgent} that reads the appropriate data during a backup operation, then +create your table and insert the data during a restore operation.</li> +</ul> + +<p>If you don't need to perform any of the tasks above and want to back up complete files from +{@link android.content.SharedPreferences} or <a +href="{@docRoot}guide/topics/data/data-storage.html#filesInternal">internal storage</a>, you +should skip to <a href="#BackupAgentHelper">Extending BackupAgentHelper</a>.</p> + + + +<h3 id="RequiredMethods">Required methods</h3> + +<p>When you create a backup agent by extending {@link android.app.backup.BackupAgent}, you +must implement the following callback methods:</p> + +<dl> + <dt>{@link +android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) +onBackup()}</dt> + <dd>The Backup Manager calls this method after you <a href="#RequestingBackup">request a +backup</a>. In this method, you read your application data from the device and pass the data you +want to back up to the Backup Manager, as described below in <a href="#PerformingBackup">Performing +backup</a>.</dd> + + <dt>{@link +android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) +onRestore()}</dt> + <dd>The Backup Manager calls this method during a restore operation (you can <a +href="#RequestingRestore">request a restore</a>, but the system automatically performs restore when +the user re-installs your application). When it calls this method, the Backup Manager delivers your +backup data, which you then restore to the device, as described below in <a +href="#PerformingRestore">Performing restore</a>.</dd> +</dl> + + + +<h3 id="PerformingBackup">Performing backup</h3> + + +<p>When it's time to back up your application data, the Backup Manager calls your {@link +android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) +onBackup()} method. This is where you must provide your application data to the Backup Manager so +it can be saved to cloud storage.</p> + +<p>Only the Backup Manager can call your backup agent's {@link +android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) +onBackup()} method. Each time that your application data changes and you want to perform a backup, +you must request a backup operation by calling {@link +android.app.backup.BackupManager#dataChanged()} (see <a href="#RequestingBackup">Requesting +Backup</a> for more information). A backup request does not result in an immediate call to your +{@link +android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) +onBackup()} method. Instead, the Backup Manager waits for an appropriate time, then performs +backup for all applications that have requested a backup since the last backup was performed.</p> + +<p class="note"><strong>Tip:</strong> While developing your application, you can initiate an +immediate backup operation from the Backup Manager with the <a +href="{@docRoot}tools/help/bmgr.html">{@code bmgr} tool</a>.</p> + +<p>When the Backup Manager calls your {@link +android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) +onBackup()} method, it passes three parameters:</p> + +<dl> + <dt>{@code oldState}</dt> + <dd>An open, read-only {@link android.os.ParcelFileDescriptor} pointing to the last backup +state provided by your application. This is not the backup data from cloud storage, but a +local representation of the data that was backed up the last time {@link +android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) +onBackup()} was called (as defined by {@code newState}, below, or from {@link +android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) +onRestore()}—more about this in the next section). Because {@link +android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) +onBackup()} does not allow you to read existing backup data in +the cloud storage, you can use this local representation to determine whether your data has changed +since the last backup.</dd> + <dt>{@code data}</dt> + <dd>A {@link android.app.backup.BackupDataOutput} object, which you use to deliver your backup +data to the Backup Manager.</dd> + <dt>{@code newState}</dt> + <dd>An open, read/write {@link android.os.ParcelFileDescriptor} pointing to a file in which +you must write a representation of the data that you delivered to {@code data} (a representation +can be as simple as the last-modified timestamp for your file). This object is +returned as {@code oldState} the next time the Backup Manager calls your {@link +android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) +onBackup()} method. If you do not write your backup data to {@code newState}, then {@code oldState} +will point to an empty file next time Backup Manager calls {@link +android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) +onBackup()}.</dd> +</dl> + +<p>Using these parameters, you should implement your {@link +android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) +onBackup()} method to do the following:</p> + +<ol> + <li>Check whether your data has changed since the last backup by comparing {@code oldState} to +your current data. How you read data in {@code oldState} depends on how you originally wrote it to +{@code newState} (see step 3). The easiest way to record the state of a file is with its +last-modified timestamp. For example, here's how you can read and compare a timestamp from {@code +oldState}: + <pre> +// Get the oldState input stream +FileInputStream instream = new FileInputStream(oldState.getFileDescriptor()); +DataInputStream in = new DataInputStream(instream); + +try { + // Get the last modified timestamp from the state file and data file + long stateModified = in.readLong(); + long fileModified = mDataFile.lastModified(); + + if (stateModified != fileModified) { + // The file has been modified, so do a backup + // Or the time on the device changed, so be safe and do a backup + } else { + // Don't back up because the file hasn't changed + return; + } +} catch (IOException e) { + // Unable to read state file... be safe and do a backup +} +</pre> + <p>If nothing has changed and you don't need to back up, skip to step 3.</p> + </li> + <li>If your data has changed, compared to {@code oldState}, write the current data to +{@code data} to back it up to the cloud storage. + <p>You must write each chunk of data as an "entity" in the {@link +android.app.backup.BackupDataOutput}. An entity is a flattened binary data +record that is identified by a unique key string. Thus, the data set that you back up is +conceptually a set of key-value pairs.</p> + <p>To add an entity to your backup data set, you must:</p> + <ol> + <li>Call {@link android.app.backup.BackupDataOutput#writeEntityHeader(String,int) +writeEntityHeader()}, passing a unique string key for the data you're about to write and the data +size.</li> + <li>Call {@link android.app.backup.BackupDataOutput#writeEntityData(byte[],int) +writeEntityData()}, passing a byte buffer that contains your data and the number of bytes to write +from the buffer (which should match the size passed to {@link +android.app.backup.BackupDataOutput#writeEntityHeader(String,int) writeEntityHeader()}).</li> + </ol> + <p>For example, the following code flattens some data into a byte stream and writes it into a +single entity:</p> + <pre> +// Create buffer stream and data output stream for our data +ByteArrayOutputStream bufStream = new ByteArrayOutputStream(); +DataOutputStream outWriter = new DataOutputStream(bufStream); +// Write structured data +outWriter.writeUTF(mPlayerName); +outWriter.writeInt(mPlayerScore); +// Send the data to the Backup Manager via the BackupDataOutput +byte[] buffer = bufStream.toByteArray(); +int len = buffer.length; +data.writeEntityHeader(TOPSCORE_BACKUP_KEY, len); +data.writeEntityData(buffer, len); +</pre> + <p>Perform this for each piece of data that you want to back up. How you divide your data into +entities is up to you (and you might use just one entity).</p> + </li> + <li>Whether or not you perform a backup (in step 2), write a representation of the current data to +the {@code newState} {@link android.os.ParcelFileDescriptor}. The Backup Manager retains this object +locally as a representation of the data that is currently backed up. It passes this back to you as +{@code oldState} the next time it calls {@link +android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) +onBackup()} so you can determine whether another backup is necessary (as handled in step 1). If you +do not write the current data state to this file, then +{@code oldState} will be empty during the next callback. + <p>The following example saves a representation of the current data into {@code newState} using +the file's last-modified timestamp:</p> + <pre> +FileOutputStream outstream = new FileOutputStream(newState.getFileDescriptor()); +DataOutputStream out = new DataOutputStream(outstream); + +long modified = mDataFile.lastModified(); +out.writeLong(modified); +</pre> + </li> +</ol> + +<p class="caution"><strong>Caution:</strong> If your application data is saved to a file, make sure +that you use synchronized statements while accessing the file so that your backup agent does not +read the file while an Activity in your application is also writing the file.</p> + + + + +<h3 id="PerformingRestore">Performing restore</h3> + +<p>When it's time to restore your application data, the Backup Manager calls your backup +agent's {@link android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) +onRestore()} method. When it calls this method, the Backup Manager delivers your backup data so +you can restore it onto the device.</p> + +<p>Only the Backup Manager can call {@link +android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) +onRestore()}, which happens automatically when the system installs your application and +finds existing backup data. However, you can request a restore operation for +your application by calling {@link +android.app.backup.BackupManager#requestRestore(RestoreObserver) requestRestore()} (see <a +href="#RequestingRestore">Requesting restore</a> for more information).</p> + +<p class="note"><strong>Note:</strong> While developing your application, you can also request a +restore operation with the <a href="{@docRoot}tools/help/bmgr.html">{@code bmgr} +tool</a>.</p> + +<p>When the Backup Manager calls your {@link +android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) +onRestore()} method, it passes three parameters:</p> + +<dl> + <dt>{@code data}</dt> + <dd>A {@link android.app.backup.BackupDataInput}, which allows you to read your backup +data.</dd> + <dt>{@code appVersionCode}</dt> + <dd>An integer representing the value of your application's <a +href="{@docRoot}guide/topics/manifest/manifest-element.html#vcode">{@code android:versionCode}</a> +manifest attribute, as it was when this data was backed up. You can use this to cross-check the +current application version and determine if the data format is compatible. For more +information about using this to handle different versions of restore data, see the section +below about <a href="#RestoreVersion">Checking the Restore Data Version</a>.</dd> + <dt>{@code newState}</dt> + <dd>An open, read/write {@link android.os.ParcelFileDescriptor} pointing to a file in which +you must write the final backup state that was provided with {@code data}. This object is +returned as {@code oldState} the next time {@link +android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) +onBackup()} is called. Recall that you must also write the same {@code newState} object in the +{@link +android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) +onBackup()} callback—also doing it here ensures that the {@code oldState} object given to +{@link +android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) +onBackup()} is valid even the first time {@link +android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) +onBackup()} is called after the device is restored.</dd> +</dl> + +<p>In your implementation of {@link +android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) +onRestore()}, you should call {@link android.app.backup.BackupDataInput#readNextHeader()} on the +{@code data} to iterate +through all entities in the data set. For each entity found, do the following:</p> + +<ol> + <li>Get the entity key with {@link android.app.backup.BackupDataInput#getKey()}.</li> + <li>Compare the entity key to a list of known key values that you should have declared as static +final strings inside your {@link android.app.backup.BackupAgent} class. When the key matches one of +your known key strings, enter into a statement to extract the entity data and save it to the device: + <ol> + <li>Get the entity data size with {@link +android.app.backup.BackupDataInput#getDataSize()} and create a byte array of that size.</li> + <li>Call {@link android.app.backup.BackupDataInput#readEntityData(byte[],int,int) +readEntityData()} and pass it the byte array, which is where the data will go, and specify the +start offset and the size to read.</li> + <li>Your byte array is now full and you can read the data and write it to the device +however you like.</li> + </ol> + </li> + <li>After you read and write your data back to the device, write the state of your data to the +{@code newState} parameter the same as you do during {@link +android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) +onBackup()}. +</ol> + +<p>For example, here's how you can restore the data backed up by the example in the previous +section:</p> + +<pre> +@Override +public void onRestore(BackupDataInput data, int appVersionCode, + ParcelFileDescriptor newState) throws IOException { + // There should be only one entity, but the safest + // way to consume it is using a while loop + while (data.readNextHeader()) { + String key = data.getKey(); + int dataSize = data.getDataSize(); + + // If the key is ours (for saving top score). Note this key was used when + // we wrote the backup entity header + if (TOPSCORE_BACKUP_KEY.equals(key)) { + // Create an input stream for the BackupDataInput + byte[] dataBuf = new byte[dataSize]; + data.readEntityData(dataBuf, 0, dataSize); + ByteArrayInputStream baStream = new ByteArrayInputStream(dataBuf); + DataInputStream in = new DataInputStream(baStream); + + // Read the player name and score from the backup data + mPlayerName = in.readUTF(); + mPlayerScore = in.readInt(); + + // Record the score on the device (to a file or something) + recordScore(mPlayerName, mPlayerScore); + } else { + // We don't know this entity key. Skip it. (Shouldn't happen.) + data.skipEntityData(); + } + } + + // Finally, write to the state blob (newState) that describes the restored data + FileOutputStream outstream = new FileOutputStream(newState.getFileDescriptor()); + DataOutputStream out = new DataOutputStream(outstream); + out.writeUTF(mPlayerName); + out.writeInt(mPlayerScore); +} +</pre> + +<p>In this example, the {@code appVersionCode} parameter passed to {@link +android.app.backup.BackupAgent#onRestore onRestore()} is not used. However, you might want to use +it if you've chosen to perform backup when the user's version of the application has actually moved +backward (for example, the user went from version 1.5 of your app to 1.0). For more information, see +the section about <a href="#RestoreVersion">Checking the Restore Data Version</a>.</p> + +<div class="special"> +<p>For an example implementation of {@link android.app.backup.BackupAgent}, see the <a +href="{@docRoot}resources/samples/BackupRestore/src/com/example/android/backuprestore/ExampleAgent.html">{@code +ExampleAgent}</a> class in the <a +href="{@docRoot}resources/samples/BackupRestore/index.html">Backup and Restore</a> sample +application.</p> +</div> + + + + + + +<h2 id="BackupAgentHelper">Extending BackupAgentHelper</h2> + +<p>You should build your backup agent using {@link android.app.backup.BackupAgentHelper} if you want +to back up complete files (from either {@link android.content.SharedPreferences} or <a +href="{@docRoot}guide/topics/data/data-storage.html#filesInternal">internal storage</a>). +Building your backup agent with {@link android.app.backup.BackupAgentHelper} requires far less +code than extending {@link android.app.backup.BackupAgent}, because you don't have to implement +{@link +android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) +onBackup()} and {@link +android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) +onRestore()}.</p> + +<p>Your implementation of {@link android.app.backup.BackupAgentHelper} must +use one or more backup helpers. A backup helper is a specialized +component that {@link android.app.backup.BackupAgentHelper} summons to perform backup and +restore operations for a particular type of data. The Android framework currently provides two +different helpers:</p> +<ul> + <li>{@link android.app.backup.SharedPreferencesBackupHelper} to backup {@link +android.content.SharedPreferences} files.</li> + <li>{@link android.app.backup.FileBackupHelper} to backup files from <a +href="{@docRoot}guide/topics/data/data-storage.html#filesInternal">internal storage</a>.</li> +</ul> + +<p>You can include multiple helpers in your {@link android.app.backup.BackupAgentHelper}, but only +one helper is needed for each data type. That is, if you have multiple {@link +android.content.SharedPreferences} files, then you need only one {@link +android.app.backup.SharedPreferencesBackupHelper}.</p> + +<p>For each helper you want to add to your {@link android.app.backup.BackupAgentHelper}, you must do +the following during your {@link android.app.backup.BackupAgent#onCreate()} method:</p> +<ol> + <li>Instantiate in instance of the desired helper class. In the class constructor, you must +specify the appropriate file(s) you want to backup.</li> + <li>Call {@link android.app.backup.BackupAgentHelper#addHelper(String,BackupHelper) addHelper()} +to add the helper to your {@link android.app.backup.BackupAgentHelper}.</li> +</ol> + +<p>The following sections describe how to create a backup agent using each of the available +helpers.</p> + + + +<h3 id="SharedPreferences">Backing up SharedPreferences</h3> + +<p>When you instantiate a {@link android.app.backup.SharedPreferencesBackupHelper}, you must +include the name of one or more {@link android.content.SharedPreferences} files.</p> + +<p>For example, to back up a {@link android.content.SharedPreferences} file named +"user_preferences", a complete backup agent using {@link android.app.backup.BackupAgentHelper} looks +like this:</p> + +<pre> +public class MyPrefsBackupAgent extends BackupAgentHelper { + // The name of the SharedPreferences file + static final String PREFS = "user_preferences"; + + // A key to uniquely identify the set of backup data + static final String PREFS_BACKUP_KEY = "prefs"; + + // Allocate a helper and add it to the backup agent + @Override + public void onCreate() { + SharedPreferencesBackupHelper helper = + new SharedPreferencesBackupHelper(this, PREFS); + addHelper(PREFS_BACKUP_KEY, helper); + } +} +</pre> + +<p>That's it! That's your entire backup agent. The {@link +android.app.backup.SharedPreferencesBackupHelper} includes all the code +needed to backup and restore a {@link android.content.SharedPreferences} file.</p> + +<p>When the Backup Manager calls {@link +android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) +onBackup()} and {@link +android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) +onRestore()}, {@link android.app.backup.BackupAgentHelper} calls your backup helpers to perform +backup and restore for your specified files.</p> + +<p class="note"><strong>Note:</strong> The methods of {@link android.content.SharedPreferences} +are threadsafe, so +you can safely read and write the shared preferences file from your backup agent and +other activities.</p> + + + +<h3 id="Files">Backing up other files</h3> + +<p>When you instantiate a {@link android.app.backup.FileBackupHelper}, you must include the name of +one or more files that are saved to your application's <a +href="{@docRoot}guide/topics/data/data-storage.html#filesInternal">internal storage</a> +(as specified by {@link android.content.ContextWrapper#getFilesDir()}, which is the same +location where {@link android.content.Context#openFileOutput(String,int) openFileOutput()} writes +files).</p> + +<p>For example, to backup two files named "scores" and "stats," a backup agent using {@link +android.app.backup.BackupAgentHelper} looks like this:</p> + +<pre> +public class MyFileBackupAgent extends BackupAgentHelper { + // The name of the file + static final String TOP_SCORES = "scores"; + static final String PLAYER_STATS = "stats"; + + // A key to uniquely identify the set of backup data + static final String FILES_BACKUP_KEY = "myfiles"; + + // Allocate a helper and add it to the backup agent + @Override + public void onCreate() { + FileBackupHelper helper = new FileBackupHelper(this, + TOP_SCORES, PLAYER_STATS); + addHelper(FILES_BACKUP_KEY, helper); + } +} +</pre> + +<p>The {@link android.app.backup.FileBackupHelper} includes all the code necessary to backup and +restore files that are saved to your application's <a +href="{@docRoot}guide/topics/data/data-storage.html#filesInternal">internal storage</a>..</p> + +<p>However, reading and writing to files on internal storage is <strong>not threadsafe</strong>. To +ensure that your backup agent does not read or write your files at the same time as your activities, +you must use synchronized statements each time you perform a read or write. For example, +in any Activity where you read and write the file, you need an object to use as the intrinsic +lock for the synchronized statements:</p> + +<pre> +// Object for intrinsic lock +static final Object sDataLock = new Object(); +</pre> + +<p>Then create a synchronized statement with this lock each time you read or write the files. For +example, here's a synchronized statement for writing the latest score in a game to a file:</p> + +<pre> +try { + synchronized (MyActivity.sDataLock) { + File dataFile = new File({@link android.content.Context#getFilesDir()}, TOP_SCORES); + RandomAccessFile raFile = new RandomAccessFile(dataFile, "rw"); + raFile.writeInt(score); + } +} catch (IOException e) { + Log.e(TAG, "Unable to write to file"); +} +</pre> + +<p>You should synchronize your read statements with the same lock.</p> + +<p>Then, in your {@link android.app.backup.BackupAgentHelper}, you must override {@link +android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) +onBackup()} and {@link +android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) +onRestore()} to synchronize the backup and restore operations with the same +intrinsic lock. For example, the {@code MyFileBackupAgent} example from above needs the following +methods:</p> + +<pre> +@Override +public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data, + ParcelFileDescriptor newState) throws IOException { + // Hold the lock while the FileBackupHelper performs backup + synchronized (MyActivity.sDataLock) { + super.onBackup(oldState, data, newState); + } +} + +@Override +public void onRestore(BackupDataInput data, int appVersionCode, + ParcelFileDescriptor newState) throws IOException { + // Hold the lock while the FileBackupHelper restores the file + synchronized (MyActivity.sDataLock) { + super.onRestore(data, appVersionCode, newState); + } +} +</pre> + +<p>That's it. All you need to do is add your {@link android.app.backup.FileBackupHelper} in the +{@link android.app.backup.BackupAgent#onCreate()} method and override {@link +android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) +onBackup()} and {@link +android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) +onRestore()} to synchronize read and write operations.</p> + +<div class="special"> +<p>For an example implementation of {@link +android.app.backup.BackupAgentHelper} with {@link android.app.backup.FileBackupHelper}, see the +{@code FileHelperExampleAgent} class in the <a +href="{@docRoot}resources/samples/BackupRestore/index.html">Backup and Restore</a> sample +application.</p> +</div> + + + + + + +<h2 id="RestoreVersion">Checking the restore data version</h2> + +<p>When the Backup Manager saves your data to cloud storage, it automatically includes the version +of your application, as defined by your manifest file's <a +href="{@docRoot}guide/topics/manifest/manifest-element.html#vcode">{@code android:versionCode}</a> +attribute. Before the Backup Manager calls your backup agent to restore your data, it +looks at the <a +href="{@docRoot}guide/topics/manifest/manifest-element.html#vcode">{@code +android:versionCode}</a> of the installed application and compares it to the value +recorded in the restore data set. If the version recorded in the restore data set is +<em>newer</em> than the application version on the device, then the user has downgraded their +application. In this case, the Backup Manager will abort the restore operation for your application +and not call your {@link +android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) onRestore()} +method, because the restore set is considered meaningless to an older version.</p> + +<p>You can override this behavior with the <a +href="{@docRoot}guide/topics/manifest/application-element.html#restoreany">{@code +android:restoreAnyVersion}</a> attribute. This attribute is either "{@code true}" or "{@code +false}" to indicate whether you want to restore the application regardless of the restore set +version. The default value is "{@code false}". If you define this to be "{@code true}" then the +Backup Manager will ignore the <a +href="{@docRoot}guide/topics/manifest/manifest-element.html#vcode">{@code android:versionCode}</a> +and call your {@link +android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) onRestore()} +method in all cases. In doing so, you can manually check for the version difference in your {@link +android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) onRestore()} +method and take any steps necessary to make the data compatible if the versions conflict.</p> + +<p>To help you handle different versions during a restore operation, the {@link +android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) onRestore()} +method passes you the version code included with the restore data set as the {@code appVersionCode} +parameter. You can then query the current application's version code with the {@link +android.content.pm.PackageInfo#versionCode PackageInfo.versionCode} field. For example:</p> + +<pre> +PackageInfo info; +try { + String name = {@link android.content.ContextWrapper#getPackageName() getPackageName}(); + info = {@link android.content.ContextWrapper#getPackageManager +getPackageManager}().{@link android.content.pm.PackageManager#getPackageInfo(String,int) +getPackageInfo}(name,0); +} catch (NameNotFoundException nnfe) { + info = null; +} + +int version; +if (info != null) { + version = info.versionCode; +} +</pre> + +<p>Then simply compare the {@code version} acquired from {@link android.content.pm.PackageInfo} +to the {@code appVersionCode} passed into {@link +android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) onRestore()}. +</p> + +<p class="caution"><strong>Caution:</strong> Be certain you understand the consequences of setting +<a href="{@docRoot}guide/topics/manifest/application-element.html#restoreany">{@code +android:restoreAnyVersion}</a> to "{@code true}" for your application. If each version of your +application that supports backup does not properly account for variations in your data format during +{@link +android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) onRestore()}, +then the data on the device could be saved in a format incompatible with the version currently +installed on the device.</p> + + + +<h2 id="RequestingBackup">Requesting backup</h2> + +<p>You can request a backup operation at any time by calling {@link +android.app.backup.BackupManager#dataChanged()}. This method notifies the Backup Manager that you'd +like to backup your data using your backup agent. The Backup Manager then calls your backup +agent's {@link +android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) +onBackup()} method at an opportune time in the future. Typically, you should +request a backup each time your data changes (such as when the user changes an application +preference that you'd like to back up). If you call {@link +android.app.backup.BackupManager#dataChanged()} several times consecutively, before the Backup +Manager requests a backup from your agent, your agent still receives just one call to {@link +android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) +onBackup()}.</p> + +<p class="note"><strong>Note:</strong> While developing your application, you can request a +backup and initiate an immediate backup operation with the <a +href="{@docRoot}tools/help/bmgr.html">{@code bmgr} +tool</a>.</p> + + +<h2 id="RequestingRestore">Requesting restore</h2> + +<p>During the normal life of your application, you shouldn't need to request a restore operation. +They system automatically checks for backup data and performs a restore when your application is +installed. However, you can manually request a restore operation by calling {@link +android.app.backup.BackupManager#requestRestore(RestoreObserver) requestRestore()}, if necessary. In +which case, the Backup Manager calls your {@link +android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) onRestore()} +implementation, passing the data from the current set of backup data.</p> + +<p class="note"><strong>Note:</strong> While developing your application, you can request a +restore operation with the <a href="{@docRoot}tools/help/bmgr.html">{@code bmgr} +tool</a>.</p> + + +<h2 id="Migrating">Migrating to Auto Backup</h2> +<p>You can transition your app to full-data backups by setting <a href="{@docRoot}reference/android/R.attr.html#fullBackupOnly">android:fullBackupOnly</a> to <code>true</code> in the <code><application></code> element in the manifest file. When +running on a device with Android 5.1 (API level 22) or lower, your app ignores +this value in the manifest, and continues performing Key/Value Backups. When +running on a device with Android 6.0 (API level 23) or higher, your app performs +Auto Backup instead of Key/Value Backup.
\ No newline at end of file diff --git a/docs/html/guide/topics/data/testingbackup.jd b/docs/html/guide/topics/data/testingbackup.jd new file mode 100644 index 000000000000..6ff5837e2411 --- /dev/null +++ b/docs/html/guide/topics/data/testingbackup.jd @@ -0,0 +1,181 @@ +page.title=Testing Backup and Restore +page.tags=backup, marshmallow, androidm +page.keywords=backup, restore, testing + +@jd:body + +<div id="qv-wrapper"> +<div id="qv"> + <h2>In this document</h2> + <ol> + <li><a href="#HowBackupWorks">How backup works</a></li> + <li><a href="#Prerequisites">Prerequisites</a></li> + <li><a href="#Preparing">Preparing your device or emulator</a></li> + <li><a href="#TestingBackup">Testing backup</a></li> + <li><a href="#TestingRestore">Testing restore</a></li> + <li><a href="#Troubleshooting">Troubleshooting</a></li> + </ol> + +</div> +</div> + +<p>This page shows you how to manually trigger Auto Backup, Key/Value Backup, and restore operations to +ensure your app saves and restores data properly. + +<h2 id="HowBackupWorkso">How backup works</h2> +<p>The section describes various pieces in the Android backup framework and how they +interact with apps that support Auto Backup and Key/Value Backup. During the app +development phase, most of the inner working of the framework were abstracted away, so you didn't need to know this information. However, during the +testing phase, an understanding of these concepts is important. + +<p>The following diagram illustrates how data flows during backup and restore: + +<img src="images/backup-framework.png" alt="backup-framework"> + +<p>The <em>Backup Manager Service</em> is an Android system +service which orchestrates and initiates backup and restore operations. The service +is accessible through the {@link android.app.backup.BackupManager} +API. During a backup operation, the service queries your app for backup data, +then hands it to the <em>backup transport</em>, which then archives the data. +During a restore operation, the backup manager service retrieves the backup data +from the backup transport and restores the data to the device. + +<p><em>Backup Transports</em> are Android components that are responsible +for storing and retrieving backups. An Android device can have zero or more +backup transports, but only one of those transports can be marked active. The +available backup transports may differ from device to device (due to +customizations by device manufacturers and service providers), but most Google +Play enabled devices ship with the following transports: +</p><ul> +<li><strong>Google GMS Transport</strong>(default) - the active backup +transport on most devices, part of <a href="https://www.android.com/gms/">Google Mobile Services</a>. This documentation assumes that users are using the +Google GMS transport. This transport stores Auto Backup data in a private folder in the +user's Google Drive account. Key/Value Backup data is stored in the <a href="{@docRoot}google/backup/index.html">Android Backup Service</a>. +<li><strong>Local Transport</strong> - stores backup data locally on the device. +This transport is typically used for development/debugging purposes and is not +useful in the real world.</li></ul> + +<p>If a device does not have any backup transports, then the data cannot be +backed up. Your app is not adversely affected. + +<p class="caution"><strong>Caution:</strong> Because the backup transport +can differ from device to device, Android cannot guarantee the security +of your data while using backup. Be cautious about using backup to store +sensitive data, such as usernames and passwords. + +<h2 id="Prerequisites">Prerequisites</h2> +<p>You need to know a bit about the following tools: + +<ul> + <li><a href="{@docRoot}studio/command-line/adb.html">adb</a> +- to run commands on the device or emulator + <li><a href="{@docRoot}studio/command-line/bmgr.html">bmgr</a> - to +perform various backup and restore operations + <li><a href="{@docRoot}studio/command-line/logcat.html">logcat</a> +- to see the output of backup and restore operations.</li></ul> + +<h2 id="Preparing">Preparing your device or +emulator</h2> +<p>Prepare your device or emulator for backup testing by working through the +following checklist: +<ul> + <li>For Auto Backup, check that you are using a device or emulator running +Android 6.0 (API level 23) or higher.</li> + <li>For Key/Value Backup, check that you are using a device or emulator running +Android 2.2 (API level 8) or higher.</li> + <li>Check that backup and restore is enabled on the device or emulator. There +are two ways to check: <ul> + <li>On the device, go to <strong>Settings -> Backup & Restore</strong>. + <li>From adb shell, run <code>bmgr enable</code></li></ul> + <p>On physical devices, backup and restore is typically enabled during the +initial setup wizard. Emulators do not run the setup wizard, so don't forget to +enable backup and specify a backup account in device settings. + <li>Make sure the GMS Backup Transport is available and active by running the +command from adb shell: + <pre class="prettyprint">$ bmgr list transports</pre> + <p>Then, check the console for the following output: + <pre class="prettyprint">android/com.android.internal.backup.LocalTransport +* com.google.android.gms/.backup.BackupTransportService</pre> + <p>Physical devices without Google Play and emulators without Google APIs +might not include the GMS Backup Transport. This article assumes you are using +the GMS Backup Transport. You can test backup and restore with other backup +transports, but the procedure and output can differ. +</ul> + +<h2 id="TestingBackup">Testing backup</h2> +<p>To initiate a backup of your app, run the following command: + +<pre class="prettyprint">$ bmgr backupnow <PACKAGE></pre> + +<p>The <code>backupnow</code> command runs either a Key/Value Backup or Auto Backup depending on +the package's manifest declarations. Check logcat to see the output of the +backup procedure. For example: + +<pre class="prettyprint">D/BackupManagerService: fullTransportBackup() +I/GmsBackupTransport: Attempt to do full backup on <PACKAGE> + +---- or ---- + +V/BackupManagerService: Scheduling immediate backup pass +D/PerformBackupTask: starting key/value Backup of BackupRequest{pkg=<PACKAGE>} +</pre> + +<p>If the <code>backupnow</code> command is not available on your device, you need to run one +of the following commands: +<ul> + <li>For Auto Backups, run: <code>bmgr fullbackup <PACKAGE></code> + <li>For Key/Value Backups, schedule and run your backup with the following +commands: + <pre class="prettyprint">$ bmgr backup <PACKAGE> +$ bmgr run</pre> + <p><code>bmgr backup</code> adds your app to the Backup Manager's queue. <code>bmgr run</code> initiates the +backup operation, which forces the Backup Manager to perform all backup requests +that are in its queue. + </li></ul> + +<h2 id="TestingRestore">Testing restore</h2> +<p>To manually initiate a restore, run the following command: + +<pre class="prettyprint">$ bmgr restore <PACKAGE></pre> + +<p>Warning: This action stops your app and wipes its data before performing the +restore operation. + +<p>Then, check logcat to see the output of the restore procedure. For example: + +<pre class="prettyprint">V/BackupManagerService: beginRestoreSession: pkg=<PACKAGE> transport=null +V/RestoreSession: restorePackage pkg=<PACKAGE> token=368abb4465c5c683 +... +I/BackupManagerService: Restore complete. +</pre> + +<p>You also can test automatic restore for your app by uninstalling and +reinstalling your app either with <code>adb</code> or through the Google +Play Store app. + +<h2 id="Troubleshooting">Troubleshooting</h2> +<p><strong>Exceeded Quota</strong> + +<p>If you see the the following messages in logcat: + +<pre class="prettyprint">I/PFTBT: Transport rejected backup of <PACKAGE>, skipping + +--- or --- + +I/PFTBT: Transport quota exceeded for package: <PACKAGE> +</pre> + +<p>Your app has exceeded the quota and has been banned from backing up +data on this device. To lift the ban, either factory reset your device or change +the backup account. + +<p><strong>Full Backup Not Possible</strong> + +<p>If you see the the following message in logcat: + +<pre class="prettyprint">I/BackupManagerService: Full backup not currently possible -- key/value backup not yet run? +</pre> + +<p>The fullbackup operation failed because no Key/Value Backup operation has yet +occurred on the device. Trigger a Key/Value Backup with the command <code>bmgr +run </code>and then try again.
\ No newline at end of file diff --git a/docs/html/training/_book.yaml b/docs/html/training/_book.yaml index e9635be74ec3..b965e6252c09 100644 --- a/docs/html/training/_book.yaml +++ b/docs/html/training/_book.yaml @@ -438,16 +438,6 @@ toc: path: /training/efficient-downloads/redundant_redundant.html - title: Modifying Patterns Based on the Connectivity Type path: /training/efficient-downloads/connectivity_patterns.html - - title: Backing up App Data to the Cloud - path: /training/backup/index.html - path_attributes: - - name: description - value: How to sync and back up app and user data to remote web services in the cloud and how to restore the data back to multiple devices. - section: - - title: Configuring Auto Backup - path: /training/backup/autosyncapi.html - - title: Using the Backup API - path: /training/backup/backupapi.html - title: Resolving Cloud Save Conflicts path: /training/cloudsave/conflict-res.html path_attributes: @@ -1156,7 +1146,7 @@ toc: value: 维护兼容性 - name: zh-tw-lang value: 維持相容性 - - title: Selecting Colors with the Palette API + - title: Selecting Colors with the Palette API path: /training/material/palette-colors.html - title: Best Practices for User Input diff --git a/docs/html/training/backup/autosyncapi.jd b/docs/html/training/backup/autosyncapi.jd deleted file mode 100644 index e0df7bb658ae..000000000000 --- a/docs/html/training/backup/autosyncapi.jd +++ /dev/null @@ -1,370 +0,0 @@ -page.title=Configuring Auto Backup for Apps -page.tags=backup, marshmallow, androidm -page.keywords=backup, autobackup -page.image=images/cards/card-auto-backup_2x.png - -@jd:body - -<div id="tb-wrapper"> -<div id="tb"> -<h2>This lesson teaches you to</h2> -<ol> - <li><a href="#configuring">Configure Data Backup</a></li> - <li><a href="#previous-androids">Support Lower Versions of Android</a></li> - <li><a href="#testing">Test Backup Configuration</a></li> - <li><a href="#issues">Handle Google Cloud Messaging</a></li> -</ol> - <h2>You should also read</h2> - <ul> - <li><a href="{@docRoot}guide/topics/data/backup.html">Data Backup</a></li> - <li><a href="{@docRoot}training/backup/backupapi.html">Using the Backup API</a> - </li> - </ul> - -</div> -</div> - -<p> - Users frequently invest time and effort to configure apps just the way they like them. Switching - to a new device can cancel out all that careful configuration. For apps whose <a href= - "{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">target SDK version</a> - is Android 6.0 (API level 23) and higher, devices running Android 6.0 and higher automatically - back up app data to the cloud. The system performs this automatic backup - for nearly all app data by default, and does so without your having to write any additional app - code. -</p> - -<p class="note"> -<strong>Note:</strong> To protect user privacy, the device user must have opted in to Google -services for Auto Backup to work. The Google services opt-in dialog appears when the user goes -through the Setup Wizard or configures the first Google account on the device. -</p> - -<p> - When a user installs your app on - a new device, or reinstalls your app on one (for example, after a factory reset), the system - automatically restores the app data from the cloud. This lesson provides information about how to - configure the Auto Backup for Apps feature, explaining its default behavior and how to - exclude data that you don't want the system to back up. -</p> - -<p> - The automatic backup feature preserves the data your app creates on a user device by uploading it - to the user’s Google Drive account and encrypting it. There is no charge to you or the user for - data storage, and the saved data does not count towards the user's personal Google Drive quota. - Each app can store up to 25MB. Once its backed-up data reaches 25MB, the app no longer sends - data to the cloud. If the system performs a data restore, it uses the last data snapshot that - the app had sent to the cloud. -</p> - -<p>Automatic backups occur when the following conditions are met:</p> - <ul> - <li>The device is idle.</li> - <li>The device is charging.</li> - <li>The device is connected to a Wi-Fi network.</li> - <li>At least 24 hours have elapsed since the last backup.</li> - </ul> -</p> - -<h2 id="configuring">Configure Data Backup</h2> - -<p> - On devices running Android 6.0 (API level 23) or higher, the default system behavior is to back up - almost all data that an app creates. The exception is <a href="#auto-exclude"> - automatically excluded data files</a>. This section explains how you can use settings in - your app <a href="{@docRoot}guide/topics/manifest/manifest-intro.html">manifest</a> to further - limit and configure what data the system backs up. -</p> - -<h3 id="include-exclude">Including or excluding data</h3> - -<p> - Depending on what data your app needs and how you save it, you may need to set specific - rules for including or excluding certain files or directories. Auto Backup for Apps - lets you set these backup rules through the app manifest, in which you specify a backup scheme - configuration XML file. For example: -</p> - -<pre> -<?xml version="1.0" encoding="utf-8"?> -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:tools="http://schemas.android.com/tools" - package="com.my.appexample"> - <uses-sdk android:minSdkVersion="23"/> - <uses-sdk android:targetSdkVersion="23"/> - <application ... -<strong> android:fullBackupContent="@xml/mybackupscheme"></strong> - </app> - ... -</manifest> -</pre> - -<p> - In this example, the <code>android:fullBackupContent</code> attribute specifies an XML file - called {@code mybackupscheme.xml}, which resides in the <code>res/xml/</code> directory of your - app development project. This configuration file contains rules controlling which files are backed - up. The following example code shows a configuration file that excludes a specific file, - {@code device_info.db}: -</p> - -<pre> -<?xml version="1.0" encoding="utf-8"?> -<full-backup-content> - <exclude domain="database" path="device_info.db"/> -</full-backup-content> -</pre> - -<h3 id="auto-exclude">Automatically excluded data files</h3> - -<p> - Most apps do not need to, and in fact should not, back up all data. For example, the system - should not back up temporary files and caches. For this reason, the automatic backup - service excludes certain data files by default: -</p> - -<ul> - <li>Files in the directories to which the - {@link android.content.Context#getCacheDir getCacheDir()} and - {@link android.content.Context#getCodeCacheDir getCodeCacheDir()} methods refer. - </li> - - <li>Files located on external storage, unless they reside in the directory to which the - {@link android.content.Context#getExternalFilesDir getExternalFilesDir()} method refers. - </li> - - <li>Files located in the directory to which the - {@link android.content.Context#getNoBackupFilesDir getNoBackupFilesDir()} method refers. - </li> -</ul> -<h3>Backup Configuration Syntax</h3> - -<p> - The backup service configuration allows you to specify what files to include or exclude from - backup. The syntax for the data backup configuration XML file is as follows: -</p> - -<pre> -<full-backup-content> - <include domain=["file" | "database" | "sharedpref" | "external" | "root"] - path="string" /> - <exclude domain=["file" | "database" | "sharedpref" | "external" | "root"] - path="string" /> -</full-backup-content> -</pre> - -<p> - The following elements and attributes allow you to specify the files to include in, and exclude - from, backup: -</p> - -<ul> - <li> - <code><include></code>: Specifies a set of resources to - back up, instead of having the system back up all data in your app by default. If you specify - an <code><include></code> element, the system backs up <em>only the resources specified</em> - with this element. You can specify multiple sets of resources to back up by using multiple - <code><include></code> elements - </li> - - <li> - <code><exclude></code>: Specifies any data you want the system to exclude - when it does a full backup. If you target the same set of resources with both the - <code><include></code> and <code><exclude></code> elements, - <code><exclude></code> takes precedence. - </li> - - <li> - <code>domain</code>: Specifies the type of resource you want to include in, - or exclude from, backup. Valid values for this attribute include: - - - - <ul> - <li> - <code>root</code>: Specifies that the resource is in the app’s root directory. - </li> - - <li> - <code>file</code>: Specifies a resource in the directory returned by the - {@link android.content.Context#getFilesDir getFilesDir()} method. - </li> - - <li> - <code>database</code>: Specifies a database that the - {@link android.content.Context#getDatabasePath getDatabasePath()} method returns, or that - the app interacts with via the {@link android.database.sqlite.SQLiteOpenHelper} class. - </li> - - <li> - <code>sharedpref</code>: Specifies a {@link android.content.SharedPreferences} object - that the {@link android.content.Context#getSharedPreferences getSharedPreferences()} - method returns. - </li> - - <li> - <code>external</code>: Specifies that the resource is in external storage, and corresponds - to a file in the directory that the - {@link android.content.Context#getExternalFilesDir getExternalFilesDir()} method returns. - </li> - </ul> - </li> - <li> - <code>path</code>: Specifies the file path to a resource that you want to include in, or - exclude from, backup. - </li> - - </li> -</ul> - - -<h3 id="disabling">Disabling data backups</h3> - -<p> - You can choose to prevent automatic backups of any of your app data by setting the - <code>android:allowBackup</code> attribute to <code>false</code> in the {@code app} element of - your manifest. This setting is illustrated in the following example: -</p> - -<pre> -<?xml version="1.0" encoding="utf-8"?> -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:tools="http://schemas.android.com/tools" - package="com.my.appexample"> - <uses-sdk android:minSdkVersion="23"/> - <uses-sdk android:targetSdkVersion="23"/> - <application ... -<strong> android:allowBackup="false"></strong> - </application> - ... -</manifest> -</pre> - -<h2 id="previous-androids">Support Lower Versions of Android</h2> - -<p>There are two scenarios in which you may also need to support versions of Android lower -than 6.0 (API level 23): You may be updating your existing app to take advantage of the -new auto backup functionality in Android 6.0, while wanting -to continue supporting earlier versions of Android. Or you may be releasing a new app, but -want to make sure devices running on versions of Android predating 6.0 also have backup -functionality.</p> - -<h3 id="updating">Updating an existing app to support auto backup</h3> - -<p>Earlier versions of Android supported a key/value-pair-based backup mechanism, in which the app -defines a subclass of {@link android.app.backup.BackupAgent} and sets -<a href="{@docRoot}guide/topics/manifest/application-element.html#agent"> -{@code android:backupAgent}</a> in its -<a href="{@docRoot}guide/topics/manifest/application-element.html">app manifest</a>. If your app -used this legacy approach, you can transition to full-data backups by adding the -{@code android:fullBackupOnly="true"} attribute to the -<a href="{@docRoot}guide/topics/manifest/application-element.html">{@code <application/>}</a> -element in the manifest. When running on a device with Android 5.1 -(API level 22) or lower, your app ignores this value in the manifest, and continues performing -backups in the previous manner.</p> - -<p>Even if you’re not using key/value backups, you can still use the approach described above to do -any custom processing in {@link android.app.Activity#onCreate(android.os.Bundle) onCreate()} -or {@link android.app.backup.BackupAgent#onFullBackup onFullBackup()}. You can also use that -approach to receive a notification when a restore operation happens in -{@link android.app.backup.BackupAgent#onRestoreFinished onRestoreFinished()}. If you want to retain -the system's default implementation of -<a href="#include-exclude">XML include/exclude rules handling</a>, call -{@link android.app.backup.BackupAgent#onFullBackup super.onFullBackup()}.</p> - -<h3 id="lower-versions">Giving your new app support for lower versions of Android</h3> - -<p>If you are creating a new app that targets Android 6.0, but you also want to enable cloud backup -for devices running on Android 5.1 (API level 22) and lower, you must also -<a href="{@docRoot}training/backup/backupapi.html">implement the Backup API</a>.</p> - -<h2 id="testing">Test Backup Configuration</h2> - -<p> - Once you have created a backup configuration, you should test it to make sure your app saves data - and can restore it properly. -</p> - - -<h3>Enabling Backup Logging</h3> - -<p> - To help determine how the backup feature is parsing your XML file, enable logging before - performing a test backup: -</p> - -<pre class="no-pretty-print"> -$ adb shell setprop log.tag.BackupXmlParserLogging VERBOSE -</pre> - -<h3>Testing Backup</h3> - -<p>To manually run a backup, first initialize the Backup Manager by executing the following - command: -</p> - -<pre class="no-pretty-print"> -$ adb shell bmgr run -</pre> - -<p> - Next, manually back up your application using the following command. Use the - <code><PACKAGE></code> parameter to specify the package name for your app: -</p> - -<pre class="no-pretty-print"> -$ adb shell bmgr fullbackup <PACKAGE></pre> - - -<h3>Testing restore</h3> - -<p> - To manually initiate a restore after the system has backed up your app data, execute the following - command, using the <code><PACKAGE></code> parameter to specify the package name for your - app: -</p> - -<pre class="noprettyprint"> -$ adb shell bmgr restore <PACKAGE> -</pre> - -<p class="warning"> - <b>Warning:</b> This action stops your app and wipes its data before performing the restore - operation. -</p> - -<p> - You can test automatic restore for your app by uninstalling and reinstalling your app. The app - data is automatically restored from the cloud once the app installation is complete. -</p> - - -<h3>Troubleshooting backups</h3> - -<p> - If backup fails, you can clear the backup data and associated metadata either by turning backup - off and on in <strong>Settings > Backup</strong>, factory-resetting the device, or - executing this command: -</p> - -<pre>$ adb shell bmgr wipe <TRANSPORT> <PACKAGE></pre> - -<p> - You must prepend <code>com.google.android.gms</code> to the {@code <TRANSPORT>} value. - To get the list of <a href="{@docRoot}google/backup/index.html">transports</a>, execute the - following command: -</p> - -<pre>$ adb shell bmgr list transports</pre> - -<h2 id="gcm">Handle Google Cloud Messaging</h2> - - <p> - For apps that use <a href="https://developers.google.com/cloud-messaging/gcm">Google Cloud - Messaging</a> (GCM) for push notifications, backing up the registration - token that Google Cloud Messaging registration returned can cause unexpected behavior in - notifications for the restored app. This is because when a user installs your app on a new device, - the app must <a href="https://developers.google.com/cloud-messaging/android/client#sample-register"> - query the GCM API for a new registration token</a>. If the old registration is present, because the - system had backed it up and restored it, the app doesn't seek the new token. To prevent this issue - from arising, exclude the registration token from the set of backed-up files. - </p> diff --git a/docs/html/training/backup/backupapi.jd b/docs/html/training/backup/backupapi.jd deleted file mode 100644 index 2f3e93943f37..000000000000 --- a/docs/html/training/backup/backupapi.jd +++ /dev/null @@ -1,200 +0,0 @@ -page.title=Using the Backup API -parent.title=Backing up App Data to the Cloud -parent.link=index.html - -trainingnavtop=true - -next.title=Making the Most of Google Cloud Messaging -next.link=gcm.html - -@jd:body - -<div id="tb-wrapper"> - <div id="tb"> - <h2>This lesson teaches you to</h2> - <ol> - <li><a href="#register">Register for the Android Backup Service</a></li> - <li><a href="#manifest">Configure Your Manifest</a></li> - <li><a href="#agent">Write Your Backup Agent</a></li> - <li><a href="#backup">Request a Backup</a></li> - <li><a href="#restore">Restore from a Backup</a></li> - </ol> - <h2>You should also read</h2> - <ul> - <li><a href="{@docRoot}guide/topics/data/backup.html">Data Backup</a></li> - <li><a href="{@docRoot}training/backup/autosyncapi.html">Configuring Auto Backup for Apps</a> - (Android 6.0 (API level 23) and higher)</li> - </ul> - </div> -</div> - -<p>When a user purchases a new device or resets their existing one, they might -expect that when Google Play restores your app back to their device during the -initial setup, the previous data associated with the app restores as well. On versions of Android -prior to 6.0 (API level 23), app data is not restored by default, and all the user's accomplishments -or settings in your app are lost.</p> -<p>For situations where the volume of data is relatively light (less than a -megabyte), like the user's preferences, notes, game high scores or other -stats, the Backup API provides a lightweight solution. This lesson walks you -through integrating the Backup API into your application, and restoring data to -new devices using the Backup API. - -<p class="note"> -<strong>Note:</strong> Devices running Android 6.0 and higher -<a href="{@docRoot}training/backup/autosyncapi.html">automatically back up</a> -nearly all data by default. -</p> - -<h2 id="register">Register for the Android Backup Service</h2> -<p>This lesson requires the use of the <a - href="{@docRoot}google/backup/index.html">Android Backup - Service</a>, which requires registration. Go ahead and <a - href="http://code.google.com/android/backup/signup.html">register here</a>. Once -that's done, the service pre-populates an XML tag for insertion in your Android -Manifest, which looks like this:</p> -<pre> -<meta-data android:name="com.google.android.backup.api_key" -android:value="ABcDe1FGHij2KlmN3oPQRs4TUvW5xYZ" /> -</pre> -<p>Note that each backup key works with a specific package name. If you have -different applications, register separate keys for each one.</p> - - -<h2 id="manifest">Configure Your Manifest</h2> -<p>Use of the Android Backup Service requires two additions to your application -manifest. First, declare the name of the class that acts as your backup agent, -then add the snippet above as a child element of the Application tag. Assuming -your backup agent is going to be called {@code TheBackupAgent}, here's an example of -what the manifest looks like with this tag included:</p> - -<pre> -<application android:label="MyApp" - android:backupAgent="TheBackupAgent"> - ... - <meta-data android:name="com.google.android.backup.api_key" - android:value="ABcDe1FGHij2KlmN3oPQRs4TUvW5xYZ" /> - ... -</application> -</pre> -<h2 id="agent">Write Your Backup Agent</h2> -<p>The easiest way to create your backup agent is by extending the wrapper class -{@link android.app.backup.BackupAgentHelper}. Creating this helper class is -actually a very simple process. Just create a class with the same name as you -used in the manifest in the previous step (in this example, {@code -TheBackupAgent}), -and extend {@code BackupAgentHelper}. Then override the {@link -android.app.backup.BackupAgent#onCreate()}.</p> - -<p>Inside the {@link android.app.backup.BackupAgent#onCreate()} method, create a {@link -android.app.backup.BackupHelper}. These helpers are -specialized classes for backing up certain kinds of data. The Android framework -currently includes two such helpers: {@link -android.app.backup.FileBackupHelper} and {@link -android.app.backup.SharedPreferencesBackupHelper}. After you create the helper -and point it at the data you want to back up, just add it to the -BackupAgentHelper using the {@link android.app.backup.BackupAgentHelper#addHelper(String, BackupHelper) addHelper()} -method, adding a key which is used to -retrieve the data later. In most cases the entire -implementation is perhaps 10 lines of code.</p> - -<p>Here's an example that backs up a high scores file.</p> - -<pre> -import android.app.backup.BackupAgentHelper; -import android.app.backup.FileBackupHelper; - - -public class TheBackupAgent extends BackupAgentHelper { - // The name of the SharedPreferences file - static final String HIGH_SCORES_FILENAME = "scores"; - - // A key to uniquely identify the set of backup data - static final String FILES_BACKUP_KEY = "myfiles"; - - // Allocate a helper and add it to the backup agent - @Override - void onCreate() { - FileBackupHelper helper = new FileBackupHelper(this, HIGH_SCORES_FILENAME); - addHelper(FILES_BACKUP_KEY, helper); - } -} -</pre> -<p>For added flexibility, {@link android.app.backup.FileBackupHelper}'s -constructor can take a variable number of filenames. You could just as easily -have backed up both a high scores file and a game progress file just by adding -an extra parameter, like this:</p> -<pre> -@Override - void onCreate() { - FileBackupHelper helper = new FileBackupHelper(this, HIGH_SCORES_FILENAME, PROGRESS_FILENAME); - addHelper(FILES_BACKUP_KEY, helper); - } -</pre> -<p>Backing up preferences is similarly easy. Create a {@link -android.app.backup.SharedPreferencesBackupHelper} the same way you did a {@link -android.app.backup.FileBackupHelper}. In this case, instead of adding filenames -to the constructor, add the names of the shared preference groups being used by -your application. Here's an example of how your backup agent helper might look if -high scores are implemented as preferences instead of a flat file:</p> - -<pre> -import android.app.backup.BackupAgentHelper; -import android.app.backup.SharedPreferencesBackupHelper; - -public class TheBackupAgent extends BackupAgentHelper { - // The names of the SharedPreferences groups that the application maintains. These - // are the same strings that are passed to getSharedPreferences(String, int). - static final String PREFS_DISPLAY = "displayprefs"; - static final String PREFS_SCORES = "highscores"; - - // An arbitrary string used within the BackupAgentHelper implementation to - // identify the SharedPreferencesBackupHelper's data. - static final String MY_PREFS_BACKUP_KEY = "myprefs"; - - // Simply allocate a helper and install it - void onCreate() { - SharedPreferencesBackupHelper helper = - new SharedPreferencesBackupHelper(this, PREFS_DISPLAY, PREFS_SCORES); - addHelper(MY_PREFS_BACKUP_KEY, helper); - } -} -</pre> - -<p>You can add as many backup helper instances to your backup agent helper as you -like, but remember that you only need one of each type. One {@link -android.app.backup.FileBackupHelper} handles all the files that you need to back up, and one -{@link android.app.backup.SharedPreferencesBackupHelper} handles all the shared -preferencegroups you need backed up. -</p> - - -<h2 id="backup">Request a Backup</h2> -<p>In order to request a backup, just create an instance of the {@link -android.app.backup.BackupManager}, and call it's {@link -android.app.backup.BackupManager#dataChanged()} method.</p> - -<pre> -import android.app.backup.BackupManager; -... - -public void requestBackup() { - BackupManager bm = new BackupManager(this); - bm.dataChanged(); -} -</pre> - -<p>This call notifies the backup manager that there is data ready to be backed -up to the cloud. At some point in the future, the backup manager then calls -your backup agent's {@link -android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor, BackupDataOutput, -ParcelFileDescriptor) onBackup()} method. You can make -the call whenever your data has changed, without having to worry about causing -excessive network activity. If you request a backup twice before a backup -occurs, the backup only occurs once.</p> - - -<h2 id="restore">Restore from a Backup</h2> -<p>Typically you shouldn't ever have to manually request a restore, as it -happens automatically when your application is installed on a device. However, -if it <em>is</em> necessary to trigger a manual restore, just call the -{@link android.app.backup.BackupManager#requestRestore(RestoreObserver) requestRestore()} method.</p> diff --git a/docs/html/training/backup/index.jd b/docs/html/training/backup/index.jd deleted file mode 100644 index 4449fde1d5c3..000000000000 --- a/docs/html/training/backup/index.jd +++ /dev/null @@ -1,47 +0,0 @@ -page.title=Backing up App Data to the Cloud -page.tags=cloud,sync,backup - -trainingnavtop=true -startpage=true - -@jd:body - -<div id="tb-wrapper"> -<div id="tb"> - -<h2>Dependencies and prerequisites</h2> -<ul> - <li>Android 2.2 (API level 8) and higher</li> -</ul> -</div> -</div> - -<p>Users often invest significant time and effort creating data and setting -preferences within apps. Preserving that data for users if they replace a broken -device or upgrade to a new one is an important part of ensuring a great user -experience.</p> - -<p>This class covers techniques for backing up data to the cloud so that -users can restore their data when recovering from a data loss (such as a factory -reset) or installing your application on a new device.</p> - -<p>It is important to note that the API for cloud backup changed with the -release of Android 6.0 (API level 23). For your app to support backup both -on devices running Android 6.0, and those running Android 5.1 (API level -22) and lower, you must implement both techniques that this class explains.</p> - -<h2>Lessons</h2> - -<dl> - <dt><strong><a href="autosyncapi.html">Configuring Auto Backup for Apps</a></strong></dt> - <dd>This lesson applies to Android 6.0 (API level 23) and higher. Learn how to accomplish - seamless app data backup and restore with zero additional lines of application code.</dd> -</dl> - -<dl> - <dt><strong><a href="backupapi.html">Using the Backup API</a></strong></dt> - <dd>This lesson applies to Android 5.1 (API level 22) and lower. Learn how to integrate the Backup - API into your Android app, so all of that app's user data, such as preferences, notes, and high - scores, updates seamlessly across all devices linked to that Google account.</dd> -</dl> - diff --git a/docs/html/training/training_toc.cs b/docs/html/training/training_toc.cs index d0dccba64d35..2845408f7238 100644 --- a/docs/html/training/training_toc.cs +++ b/docs/html/training/training_toc.cs @@ -649,25 +649,7 @@ </li> </ul> </li> - <li class="nav-section"> - <div class="nav-section-header"> - <a href="<?cs var:toroot ?>training/backup/index.html" - description= - "How to sync and back up app and user data to remote web services in the - cloud and how to restore the data back to multiple devices." - >Backing up App Data to the Cloud</a> - </div> - <ul> - <li><a href="<?cs var:toroot ?>training/backup/autosyncapi.html"> - Configuring Auto Backup - </a> - </li> - <li><a href="<?cs var:toroot ?>training/backup/backupapi.html"> - Using the Backup API - </a> - </li> - </ul> <li><a href="<?cs var:toroot ?>training/cloudsave/conflict-res.html" description= "How to design a robust conflict resolution strategy for apps that save data to the cloud." |