diff options
author | Alexander Lucas <alexlucas@google.com> | 2012-04-18 20:22:53 -0700 |
---|---|---|
committer | Android Git Automerger <android-git-automerger@android.com> | 2012-04-18 20:22:53 -0700 |
commit | d5014591bcfd278fb181dc61c1cd522085acaa56 (patch) | |
tree | c3018cdabbf7d97e7b5537fe6c84480e58571151 /docs | |
parent | 3a0f94da02f1499223f91b0d24e0e745af3abac5 (diff) | |
parent | 941fceedad1d2d28358dd81069c2028cbd4fb680 (diff) | |
download | frameworks_base-d5014591bcfd278fb181dc61c1cd522085acaa56.zip frameworks_base-d5014591bcfd278fb181dc61c1cd522085acaa56.tar.gz frameworks_base-d5014591bcfd278fb181dc61c1cd522085acaa56.tar.bz2 |
am 941fceed: am 773740ed: Initial commit of backup API section of cloudsync class.
* commit '941fceedad1d2d28358dd81069c2028cbd4fb680':
Initial commit of backup API section of cloudsync class.
Diffstat (limited to 'docs')
-rw-r--r-- | docs/html/resources/resources_toc.cs | 29 | ||||
-rw-r--r-- | docs/html/training/cloudsync/aesync.jd | 432 | ||||
-rw-r--r-- | docs/html/training/cloudsync/backupapi.jd | 193 | ||||
-rw-r--r-- | docs/html/training/cloudsync/index.jd | 34 |
4 files changed, 683 insertions, 5 deletions
diff --git a/docs/html/resources/resources_toc.cs b/docs/html/resources/resources_toc.cs index 686bde3..a21708c 100644 --- a/docs/html/resources/resources_toc.cs +++ b/docs/html/resources/resources_toc.cs @@ -124,6 +124,23 @@ class="new"> new!</span></span> </li> <li class="toggle-list"> + <div><a href="<?cs var:toroot ?>training/cloudsync/index.html"> + <span class="en">Syncing to the Cloud<span class="new"> new!</span></span> + </a></div> + <ul> + <li><a href="<?cs var:toroot ?>training/cloudsync/aesync.html"> + <span class="en">Syncing with App Engine</span> + </a> + </li> + <li><a href="<?cs var:toroot ?>training/cloudsync/backupapi.html"> + <span class="en">Using the Backup API</span> + </a> + </li> + </ul> + </li> + + + <li class="toggle-list"> <div><a href="<?cs var:toroot ?>training/search/index.html"> <span class="en">Adding Search Functionality<span class="new"> new!</span></span> </a> @@ -369,11 +386,11 @@ class="new"> new!</span></span> </li> <li><a href="<?cs var:toroot ?>training/displaying-bitmaps/display-bitmap.html"> <span class="en">Displaying Bitmaps in Your UI</span> - </a> </li> - </ul> + <ul> </li> + <li class="toggle-list"> <div><a href="<?cs var:toroot ?>training/accessibility/index.html"> <span class="en">Implementing Accessibility<span class="new"> new!</span></span> @@ -391,9 +408,11 @@ class="new"> new!</span></span> </li> </ul> - </li> - - + </li> + + + + <li> <span class="heading"> <span class="en">Technical Resources</span> diff --git a/docs/html/training/cloudsync/aesync.jd b/docs/html/training/cloudsync/aesync.jd new file mode 100644 index 0000000..c60d28b --- /dev/null +++ b/docs/html/training/cloudsync/aesync.jd @@ -0,0 +1,432 @@ +page.title=Syncing with App Engine +parent.title=Syncing to the Cloud +parent.link=index.html + +trainingnavtop=true +next.title=Using the Backup API +next.link=backupapi.html + +@jd:body + +<div id="tb-wrapper"> +<div id="tb"> + +<!-- table of contents --> +<h2>This lesson teaches you how to</h2> +<ol> + <li><a href="#prepare">Prepare Your Environment</a></li> + <li><a href="#project">Create Your Project</a></li> + <li><a href="#data">Create the Data Layer</a></li> + <li><a href="#persistence">Create the Persistence Layer</a></li> + <li><a href="#androidapp">Query and Update from the Android App</a></li> + <li><a href="#serverc2dm">Configure the C2DM Server-Side</a></li> + <li><a href="#clientc2dm">Configure the C2DM Client-Side</a></li> +</ol> +<h2>You should also read</h2> + <ul> + <li><a + href="http://developers.google.com/appengine/">App Engine</a></li> + <li><a href="http://code.google.com/android/c2dm/">Android Cloud to Device + Messaging Framework</a></li> + </ul> +<h2>Try it out</h2> + +<p>This lesson uses the Cloud Tasks sample code, originally shown at the +<a href="http://www.youtube.com/watch?v=M7SxNNC429U">Android + AppEngine: A Developer's Dream Combination</a> +talk at Google I/O. You can use the sample application as a source of reusable code for your own +application, or simply as a reference for how the Android and cloud pieces of the overall +application fit together. You can also build the sample application and see how it runs +on your own device or emulator.</p> +<p> + <a href="http://code.google.com/p/cloud-tasks-io/" class="button">Cloud Tasks + App</a> +</p> + +</div> +</div> + +<p>Writing an app that syncs to the cloud can be a challenge. There are many little +details to get right, like server-side auth, client-side auth, a shared data +model, and an API. One way to make this much easier is to use the Google Plugin +for Eclipse, which handles a lot of the plumbing for you when building Android +and App Engine applications that talk to each other. This lesson walks you through building such a project.</p> + +<p>Following this lesson shows you how to:</p> +<ul> + <li>Build Android and Appengine apps that can communicate with each other</li> + <li>Take advantage of Cloud to Device Messaging (C2DM) so your Android app doesn't have to poll for updates</li> +</ul> + +<p>This lesson focuses on local development, and does not cover distribution +(i.e, pushing your App Engine app live, or publishing your Android App to +market), as those topics are covered extensively elsewhere.</p> + +<h2 id="prepare">Prepare Your Environment</h2> +<p>If you want to follow along with the code example in this lesson, you must do +the following to prepare your development environment:</p> +<ul> +<li>Install the <a href="http://code.google.com/eclipse/">Google Plugin for + Eclipse.</a></li> +<li>Install the <a + href="http://code.google.com/webtoolkit/download.html">GWT SDK</a> and the <a + href="http://code.google.com/appengine/">Java App Engine SDK</a>. The <a + href="http://code.google.com/eclipse/docs/getting_started.html">Quick Start + Guide</a> shows you how to install these components.</li> +<li>Sign up for <a href="http://code.google.com/android/c2dm/signup.html">C2DM + access</a>. We strongly recommend <a + href="https://accounts.google.com/SignUp">creating a new Google account</a> specifically for +connecting to C2DM. The server component in this lesson uses this <em>role + account</em> repeatedly to authenticate with Google servers. +</li> +</ul> + +<h2 id="project">Create Your Projects</h2> +<p>After installing the Google Plugin for Eclipse, notice that a new kind of Android project +exists when you create a new Eclipse project: The <strong>App Engine Connected + Android Project</strong> (under the <strong>Google</strong> project category). +A wizard guides you through creating this project, +during the course of which you are prompted to enter the account credentials for the role +account you created.</p> + +<p class="note"><strong>Note:</strong> Remember to enter the credentials for +your <i>role account</i> (the one you created to access C2DM services), not an +account you'd log into as a user, or as an admin.</p> + +<p>Once you're done, you'll see two projects waiting for you in your +workspace—An Android application and an App Engine application. Hooray! +These two applications are already fully functional— the wizard has +created a sample application which lets you authenticate to the App Engine +application from your Android device using AccountManager (no need to type in +your credentials), and an App Engine app that can send messages to any logged-in +device using C2DM. In order to spin up your application and take it for a test +drive, do the following:</p> + +<p>To spin up the Android application, make sure you have an AVD with a platform +version of <em>at least</em> Android 2.2 (API Level 8). Right click on the Android project in +Eclipse, and go to <strong>Debug As > Local App Engine Connected Android + Application</strong>. This launches the emulator in such a way that it can +test C2DM functionality (which typically works through Google Play). It'll +also launch a local instance of App Engine containing your awesome +application.</p> + +<h2 id="data">Create the Data Layer</h2> + +<p>At this point you have a fully functional sample application running. Now +it's time to start changing the code to create your own application.</p> + +<p>First, create the data model that defines the data shared between +the App Engine and Android applications. To start, open up the source folder of +your App Engine project, and navigate down to the <strong>(yourApp)-AppEngine + > src > (yourapp) > server</strong> package. Create a new class in there containing some data you want to +store server-side. The code ends up looking something like this:</p> +<pre> +package com.cloudtasks.server; + +import javax.persistence.*; + +@Entity +public class Task { + + private String emailAddress; + private String name; + private String userId; + private String note; + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + public Task() { + } + + public String getEmailAddress() { + return this.emailAddress; + } + + public Long getId() { + return this.id; + } + ... +} +</pre> +<p>Note the use of annotations: <code>Entity</code>, <code>Id</code> and +<code>GeneratedValue</code> are all part of the <a + href="http://www.oracle.com/technetwork/articles/javaee/jpa-137156.html">Java + Persistence API</a>. Essentially, the <code>Entity</code> annotation goes +above the class declaration, and indicates that this class represents an entity +in your data layer. The <code>Id</code> and <code>GeneratedValue</code> +annotations, respectively, indicate the field used as a lookup key for this +class, and how that id is generated (in this case, +<code>GenerationType.IDENTITY</code> indicates that the is generated by +the database). You can find more on this topic in the App Engine documentation, +on the page <a + href="http://code.google.com/appengine/docs/java/datastore/jpa/overview.html">Using + JPA with App Engine</a>.</p> + +<p>Once you've written all the classes that represent entities in your data +layer, you need a way for the Android and App Engine applications to communicate +about this data. This communication is enabled by creating a Remote Procedure +Call (RPC) service. +Typically, this involves a lot of monotonous code. Fortunately, there's an easy way! Right +click on the server project in your App Engine source folder, and in the context +menu, navigate to <strong>New > Other</strong> and then, in the resulting +screen, select <strong>Google > RPC Service.</strong> A wizard appears, pre-populated +with all the Entities you created in the previous step, +which it found by seeking out the <code>@Entity</code> annotation in the +source files you added. Pretty neat, right? Click <strong>Finish</strong>, and the wizard +creates a Service class with stub methods for the Create, Retrieve, Update and +Delete (CRUD) operations of all your entities.</p> + +<h2 id="persistence">Create the Persistence Layer</h2> + +<p>The persistence layer is where your application data is stored +long-term, so any information you want to keep for your users needs to go here. +You have several options for writing your persistence layer, depending on +what kind of data you want to store. A few of the options hosted by Google +(though you don't have to use these services) include <a + href="http://code.google.com/apis/storage/">Google Storage for Developers</a> +and App Engine's built-in <a + href="http://code.google.com/appengine/docs/java/gettingstarted/usingdatastore.html">Datastore</a>. +The sample code for this lesson uses DataStore code.</p> + +<p>Create a class in your <code>com.cloudtasks.server</code> package to handle +persistence layer input and output. In order to access the data store, use the <a + href="http://db.apache.org/jdo/api20/apidocs/javax/jdo/PersistenceManager.html">PersistenceManager</a> +class. You can generate an instance of this class using the PMF class in the +<code>com.google.android.c2dm.server.PMF</code> package, and then use that to +perform basic CRUD operations on your data store, like this:</p> +<pre> +/** +* Remove this object from the data store. +*/ +public void delete(Long id) { + PersistenceManager pm = PMF.get().getPersistenceManager(); + try { + Task item = pm.getObjectById(Task.class, id); + pm.deletePersistent(item); + } finally { + pm.close(); + } +} +</pre> + +<p>You can also use <a + href="http://code.google.com/appengine/docs/python/datastore/queryclass.html">Query</a> +objects to retrieve data from your Datastore. Here's an example of a method +that searches out an object by its ID.</p> + +<pre> +public Task find(Long id) { + if (id == null) { + return null; + } + + PersistenceManager pm = PMF.get().getPersistenceManager(); + try { + Query query = pm.newQuery("select from " + Task.class.getName() + + " where id==" + id.toString() + " && emailAddress=='" + getUserEmail() + "'"); + List<Task> list = (List<Task>) query.execute(); + return list.size() == 0 ? null : list.get(0); + } catch (RuntimeException e) { + System.out.println(e); + throw e; + } finally { + pm.close(); + } +} +</pre> + +<p>For a good example of a class that encapsulates the persistence layer for +you, check out the <a + href="http://code.google.com/p/cloud-tasks-io/source/browse/trunk/CloudTasks-AppEngine/src/com/cloudtasks/server/DataStore.java">DataStore</a> +class in the Cloud Tasks app.</p> + + + +<h2 id="androidapp">Query and Update from the Android App</h2> + +<p>In order to keep in sync with the App Engine application, your Android application +needs to know how to do two things: Pull data from the cloud, and send data up +to the cloud. Much of the plumbing for this is generated by the +plugin, but you need to wire it up to your Android user interface yourself.</p> + +<p>Pop open the source code for the main Activity in your project and look for +<code><YourProjectName> Activity.java</code>, then for the method +<code>setHelloWorldScreenContent()</code>. Obviously you're not building a +HelloWorld app, so delete this method entirely and replace it +with something relevant. However, the boilerplate code has some very important +characteristics. For one, the code that communicates with the cloud is wrapped +in an {@link android.os.AsyncTask} and therefore <em>not</em> hitting the +network on the UI thread. Also, it gives an easy template for how to access +the cloud in your own code, using the <a + href="http://code.google.com/webtoolkit/doc/latest/DevGuideRequestFactory.html">RequestFactory</a> +class generated that was auto-generated for you by the Eclipse plugin (called +MyRequestFactory in the example below), and various {@code Request} types.</p> + +<p>For instance, if your server-side data model included an object called {@code +Task} when you generated an RPC layer it automatically created a +{@code TaskRequest} class for you, as well as a {@code TaskProxy} representing the individual +task. In code, requesting a list of all these tasks from the server looks +like this:</p> + +<pre> +public void fetchTasks (Long id) { + // Request is wrapped in an AsyncTask to avoid making a network request + // on the UI thread. + new AsyncTask<Long, Void, List<TaskProxy>>() { + @Override + protected List<TaskProxy> doInBackground(Long... arguments) { + final List<TaskProxy> list = new ArrayList<TaskProxy>(); + MyRequestFactory factory = Util.getRequestFactory(mContext, + MyRequestFactory.class); + TaskRequest taskRequest = factory.taskNinjaRequest(); + + if (arguments.length == 0 || arguments[0] == -1) { + factory.taskRequest().queryTasks().fire(new Receiver<List<TaskProxy>>() { + @Override + public void onSuccess(List<TaskProxy> arg0) { + list.addAll(arg0); + } + }); + } else { + newTask = true; + factory.taskRequest().readTask(arguments[0]).fire(new Receiver<TaskProxy>() { + @Override + public void onSuccess(TaskProxy arg0) { + list.add(arg0); + } + }); + } + return list; + } + + @Override + protected void onPostExecute(List<TaskProxy> result) { + TaskNinjaActivity.this.dump(result); + } + + }.execute(id); +} +... + +public void dump (List<TaskProxy> tasks) { + for (TaskProxy task : tasks) { + Log.i("Task output", task.getName() + "\n" + task.getNote()); + } +} +</pre> + +<p>This {@link android.os.AsyncTask} returns a list of +<code>TaskProxy</code> objects, and sends it to the debug {@code dump()} method +upon completion. Note that if the argument list is empty, or the first argument +is a -1, all tasks are retrieved from the server. Otherwise, only the ones with +IDs in the supplied list are returned. All the fields you added to the task +entity when building out the App Engine application are available via get/set +methods in the <code>TaskProxy</code> class.</p> + +<p>In order to create new tasks and send them to the cloud, create a request +object and use it to create a proxy object. Then populate the proxy object and +call its update method. Once again, this should be done in an +<code>AsyncTask</code> to avoid doing networking on the UI thread. The end +result looks something like this.</p> + +<pre> +new AsyncTask<Void, Void, Void>() { + @Override + protected Void doInBackground(Void... arg0) { + MyRequestFactory factory = (MyRequestFactory) + Util.getRequestFactory(TasksActivity.this, + MyRequestFactory.class); + TaskRequest request = factory.taskRequest(); + + // Create your local proxy object, populate it + TaskProxy task = request.create(TaskProxy.class); + task.setName(taskName); + task.setNote(taskDetails); + task.setDueDate(dueDate); + + // To the cloud! + request.updateTask(task).fire(); + return null; + } +}.execute(); +</pre> + +<h2 id="serverc2dm">Configure the C2DM Server-Side</h2> + +<p>In order to set up C2DM messages to be sent to your Android device, go back +into your App Engine codebase, and open up the service class that was created +when you generated your RPC layer. If the name of your project is Foo, +this class is called FooService. Add a line to each of the methods for +adding, deleting, or updating data so that a C2DM message is sent to the +user's device. Here's an example of an update task: +</p> + +<pre> +public static Task updateTask(Task task) { + task.setEmailAddress(DataStore.getUserEmail()); + task = db.update(task); + DataStore.sendC2DMUpdate(TaskChange.UPDATE + TaskChange.SEPARATOR + task.getId()); + return task; +} + +// Helper method. Given a String, send it to the current user's device via C2DM. +public static void sendC2DMUpdate(String message) { + UserService userService = UserServiceFactory.getUserService(); + User user = userService.getCurrentUser(); + ServletContext context = RequestFactoryServlet.getThreadLocalRequest().getSession().getServletContext(); + SendMessage.sendMessage(context, user.getEmail(), message); +} +</pre> + +<p>In the following example, a helper class, {@code TaskChange}, has been created with a few +constants. Creating such a helper class makes managing the communication +between App Engine and Android apps much easier. Just create it in the shared +folder, define a few constants (flags for what kind of message you're sending +and a seperator is typically enough), and you're done. By way of example, +the above code works off of a {@code TaskChange} class defined as this:</p> + +<pre> +public class TaskChange { + public static String UPDATE = "Update"; + public static String DELETE = "Delete"; + public static String SEPARATOR = ":"; +} +</pre> + +<h2 id="clientc2dm">Configure the C2DM Client-Side</h2> + +<p>In order to define the Android applications behavior when a C2DM is recieved, +open up the <code>C2DMReceiver</code> class, and browse to the +<code>onMessage()</code> method. Tweak this method to update based on the content +of the message.</p> +<pre> +//In your C2DMReceiver class + +public void notifyListener(Intent intent) { + if (listener != null) { + Bundle extras = intent.getExtras(); + if (extras != null) { + String message = (String) extras.get("message"); + String[] messages = message.split(Pattern.quote(TaskChange.SEPARATOR)); + listener.onTaskUpdated(messages[0], Long.parseLong(messages[1])); + } + } +} +</pre> + +<pre> +// Elsewhere in your code, wherever it makes sense to perform local updates +public void onTasksUpdated(String messageType, Long id) { + if (messageType.equals(TaskChange.DELETE)) { + // Delete this task from your local data store + ... + } else { + // Call that monstrous Asynctask defined earlier. + fetchTasks(id); + } +} +</pre> +<p> +Once you have C2DM set up to trigger local updates, you're all done. +Congratulations, you have a cloud-connected Android application!</p> diff --git a/docs/html/training/cloudsync/backupapi.jd b/docs/html/training/cloudsync/backupapi.jd new file mode 100644 index 0000000..3055596 --- /dev/null +++ b/docs/html/training/cloudsync/backupapi.jd @@ -0,0 +1,193 @@ +page.title=Using the Backup API +parent.title=Syncing to the Cloud +parent.link=index.html + +trainingnavtop=true +previous.title=Syncing with App Engine +previous.link=aesync.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="http://developer.android.com/guide/topics/data/backup.html">Data + Backup</a></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. By +default, that doesn't happen 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> + +<h2 id="register">Register for the Android Backup Service</h2> +<p>This lesson requires the use of the <a + href="http://code.google.com/android/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/cloudsync/index.jd b/docs/html/training/cloudsync/index.jd new file mode 100644 index 0000000..e53844b --- /dev/null +++ b/docs/html/training/cloudsync/index.jd @@ -0,0 +1,34 @@ +page.title=Syncing to the Cloud + +trainingnavtop=true +startpage=true +next.title=Syncing with App Engine +next.link=aesync.html + +@jd:body + +<p>By providing powerful APIs for internet connectivity, the Android framework +helps you build rich cloud-enabled apps that sync their data to a remote web +service, making sure all your devices always stay in sync, and your valuable +data is always backed up to the cloud.</p> + +<p>This class covers different strategies for cloud enabled applications. It +covers syncing data with the cloud using your own back-end web application, and +backing up data using the cloud so that users can restore their data when +installing your application on a new device. +</p> + +<h2>Lessons</h2> + +<dl> + <dt><strong><a href="aesync.html">Syncing with App Engine.</a></strong></dt> + <dd>Learn how to create a paired App Engine app and Android app which share a + data model, authenticates using the AccountManager, and communicate with each + other via REST and C2DM.</dd> + <dt><strong><a href="backupapi.html">Using the Backup + API</a></strong></dt> + <dd>Learn how to integrate the Backup API into your Android Application, so + that user data such as preferences, notes, and high scores update seamlessly + across all of a user's devices</dd> +</dl> + |