Android开发训练之第五章第四节——Syncing to the Cloud

Syncing to the Cloud

GET STARTED

DEPENDENCIES AND PREREQUISITES

  • Android 2.2 (API level 8) and higher

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.

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.

Lessons


Using the Backup API
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
Making the Most of Google Cloud Messaging
Learn how to efficiently send multicast messages, react intelligently to incoming Google Cloud Messaging (GCM) messages, and use GCM messages to efficiently sync with the server.

Using the Backup API

PREVIOUSNEXT

THIS LESSON TEACHES YOU TO

  1. Register for the Android Backup Service
  2. Configure Your Manifest
  3. Write Your Backup Agent
  4. Request a Backup
  5. Restore from a Backup

YOU SHOULD ALSO READ

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.

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.

Register for the Android Backup Service



This lesson requires the use of the Android Backup Service, which requires registration. Go ahead and register here. Once that‘s done, the service pre-populates an XML tag for insertion in your Android Manifest, which looks like this:

<meta-data android:name="com.google.android.backup.api_key"android:value="ABcDe1FGHij2KlmN3oPQRs4TUvW5xYZ" />

Note that each backup key works with a specific package name. If you have different applications, register separate keys for each one.

Configure Your Manifest



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 TheBackupAgent, here‘s an example of what the manifest looks like with this tag included:

<application android:label="MyApp"             android:backupAgent="TheBackupAgent">    ...    <meta-data android:name="com.google.android.backup.api_key"    android:value="ABcDe1FGHij2KlmN3oPQRs4TUvW5xYZ" />    ...</application>

Write Your Backup Agent



The easiest way to create your backup agent is by extending the wrapper class 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, TheBackupAgent), and extend BackupAgentHelper. Then override theonCreate().

Inside the onCreate() method, create a BackupHelper. These helpers are specialized classes for backing up certain kinds of data. The Android framework currently includes two such helpers: FileBackupHelper andSharedPreferencesBackupHelper. After you create the helper and point it at the data you want to back up, just add it to the BackupAgentHelper using the 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.

Here‘s an example that backs up a high scores file.

 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);    }}

For added flexibility, 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:

    @Override    void onCreate() {        FileBackupHelper helper = new FileBackupHelper(this, HIGH_SCORES_FILENAME, PROGRESS_FILENAME);        addHelper(FILES_BACKUP_KEY, helper);    }

Backing up preferences is similarly easy. Create a SharedPreferencesBackupHelper the same way you did aFileBackupHelper. 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:

 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);     } }

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 FileBackupHelper handles all the files that you need to back up, and oneSharedPreferencesBackupHelper handles all the shared preferencegroups you need backed up.

Request a Backup



In order to request a backup, just create an instance of the BackupManager, and call it‘s dataChanged() method.

 import android.app.backup.BackupManager; ...

 public void requestBackup() {   BackupManager bm = new BackupManager(this);   bm.dataChanged(); }

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 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.

Restore from a Backup



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 is necessary to trigger a manual restore, just call therequestRestore() method.

Making the Most of Google Cloud Messaging

PREVIOUSNEXT

THIS LESSON TEACHES YOU TO

  1. Send Multicast Messages Efficiently
  2. Collapse Messages that can Be Replaced
  3. Embed Data Directly in the GCM Message
  4. React Intelligently to GCM Messages

YOU SHOULD ALSO READ

Google Cloud Messaging (GCM) is a free service for sending messages to Android devices. GCM messaging can greatly enhance the user experience. Your application can stay up to date without wasting battery power on waking up the radio and polling the server when there are no updates. Also, GCM allows you to attach up to 1,000 recipients to a single message, letting you easily contact large user bases quickly when appropriate, while minimizing the work load on your server.

This lesson covers some of the best practices for integrating GCM into your application, and assumes you are already familiar with basic implementation of this service. If this is not the case, you can read the GCM demo app tutorial.

Send Multicast Messages Efficiently



One of the most useful features in GCM is support for up to 1,000 recipients for a single message. This capability makes it much easier to send out important messages to your entire user base. For instance, let‘s say you had a message that needed to be sent to 1,000,000 of your users, and your server could handle sending out about 500 messages per second. If you send each message with only a single recipient, it would take 1,000,000/500 = 2,000 seconds, or around half an hour. However, attaching 1,000 recipients to each message, the total time required to send a message out to 1,000,000 recipients becomes (1,000,000/1,000) / 500 = 2 seconds. This is not only useful, but important for timely data, such as natural disaster alerts or sports scores, where a 30 minute interval might render the information useless.

Taking advantage of this functionality is easy. If you‘re using the GCM helper library for Java, simply provide aList collection of registration IDs to the send or sendNoRetry method, instead of a single registration ID.

// This method name is completely fabricated, but you get the idea.List regIds = whoShouldISendThisTo(message);

// If you want the SDK to automatically retry a certain number of times, use the// standard send method.MulticastResult result = sender.send(message, regIds, 5);

// Otherwise, use sendNoRetry.MulticastResult result = sender.sendNoRetry(message, regIds);

For those implementing GCM support in a language other than Java, construct an HTTP POST request with the following headers:

  • Authorization: key=YOUR_API_KEY
  • Content-type: application/json

Then encode the parameters you want into a JSON object, listing all the registration IDs under the keyregistration_ids. The snippet below serves as an example. All parameters except registration_ids are optional, and the items nested in data represent the user-defined payload, not GCM-defined parameters. The endpoint for this HTTP POST message will be https://android.googleapis.com/gcm/send.

{ "collapse_key": "score_update",   "time_to_live": 108,   "delay_while_idle": true,   "data": {       "score": "4 x 8",       "time": "15:16.2342"   },   "registration_ids":["4", "8", "15", "16", "23", "42"]}

For a more thorough overview of the format of multicast GCM messages, see the Sending Messages section of the GCM guide.

Collapse Messages that Can Be Replaced



GCM messages are often a tickle, telling the mobile application to contact the server for fresh data. In GCM, it‘s possible (and recommended) to create collapsible messages for this situation, wherein new messages replace older ones. Let‘s take the example of sports scores. If you send out a message to all users following a certain game with the updated score, and then 15 minutes later an updated score message goes out, the earlier one no longer matters. For any users who haven‘t received the first message yet, there‘s no reason to send both, and force the device to react (and possibly alert the user) twice when only one of the messages is still important.

When you define a collapse key, when multiple messages are queued up in the GCM servers for the same user, only the last one with any given collapse key is delivered. For a situation like with sports scores, this saves the device from doing needless work and potentially over-notifying the user. For situations that involve a server sync (like checking email), this can cut down on the number of syncs the device has to do. For instance, if there are 10 emails waiting on the server, and ten "new email" GCM tickles have been sent to the device, it only needs one, since it should only sync once.

In order to use this feature, just add a collapse key to your outgoing message. If you‘re using the GCM helper library, use the Message class‘s collapseKey(String key) method.

Message message = new Message.Builder(regId)    .collapseKey("game4_scores") // The key for game 4.    .ttl(600) // Time in seconds to keep message queued if device offline.    .delayWhileIdle(true) // Wait for device to become active before sending.    .addPayload("key1", "value1")    .addPayload("key2", "value2")    .build();

If not using the helper library, simply add a variable to the POST header you‘re constructing, with collapse_key as the field name, and the string you‘re using for that set of updates as the value.

Embed Data Directly in the GCM Message



Often, GCM messages are meant to be a tickle, or indication to the device that there‘s fresh data waiting on a server somewhere. However, a GCM message can be up to 4kb in size, so sometimes it makes sense to simply send the data within the GCM message itself, so that the device doesn‘t need to contact the server at all. Consider this approach for situations where all of the following statements are true:

  • The total data fits inside the 4kb limit.
  • Each message is important, and should be preserved.
  • It doesn‘t make sense to collapse multiple GCM messages into a single "new data on the server" tickle.

For instance, short messages or encoded player moves in a turn-based network game are examples of good use-cases for data to embed directly into a GCM message. Email is an example of a bad use-case, since messages are often larger than 4kb, and users don‘t need a GCM message for each email waiting for them on the server.

Also consider this approach when sending multicast messages, so you don‘t tell every device across your user base to hit your server for updates simultaneously.

This strategy isn‘t appropriate for sending large amounts of data, for a few reasons:

  • Rate limits are in place to prevent malicious or poorly coded apps from spamming an individual device with messages.
  • Messages aren‘t guaranteed to arrive in-order.
  • Messages aren‘t guaranteed to arrive as fast as you send them out. Even if the device receives one GCM message a second, at a max of 1K, that‘s 8kbps, or about the speed of home dial-up internet in the early 1990‘s. Your app rating on Google Play will reflect having done that to your users.

When used appropriately, directly embedding data in the GCM message can speed up the perceived speediness of your application, by letting it skip a round trip to the server.

React Intelligently to GCM Messages



Your application should not only react to incoming GCM messages, but react intelligently. How to react depends on the context.

Don‘t be irritating

When it comes to alerting your user of fresh data, it‘s easy to cross the line from "useful" to "annoying". If your application uses status bar notifications, update your existing notification instead of creating a second one. If you beep or vibrate to alert the user, consider setting up a timer. Don‘t let the application alert more than once a minute, lest users be tempted to uninstall your application, turn the device off, or toss it in a nearby river.

Sync smarter, not harder

When using GCM as an indicator to the device that data needs to be downloaded from the server, remember you have 4kb of metadata you can send along to help your application be smart about it. For instance, if you have a feed reading app, and your user has 100 feeds that they follow, help the device be smart about what it downloads from the server! Look at the following examples of what metadata is sent to your application in the GCM payload, and how the application can react:

  • refresh — Your app basically got told to request a dump of every feed it follows. Your app would either need to send feed requests to 100 different servers, or if you have an aggregator on your server, send a request to retrieve, bundle and transmit recent data from 100 different feeds, every time one updates.
  • refreshfeedID — Better: Your app knows to check a specific feed for updates.
  • refreshfeedIDtimestamp — Best: If the user happened to manually refresh before the GCM message arrived, the application can compare timestamps of the most recent post, and determine that it doesn‘t need to do anything.
时间: 2024-10-08 10:18:47

Android开发训练之第五章第四节——Syncing to the Cloud的相关文章

Android开发训练之第五章——Building Apps with Connectivity &amp; the Cloud

Building Apps with Connectivity & the Cloud These classes teach you how to connect your app to the world beyond the user's device. You'll learn how to connect to other devices in the area, connect to the Internet, backup and sync your app's data, and

Android开发训练之第五章第三节——Transferring Data Without Draining the Battery

Transferring Data Without Draining the Battery GET STARTED DEPENDENCIES AND PREREQUISITES Android 2.0 (API Level 5) or higher YOU SHOULD ALSO READ Optimizing Battery Life In this class you will learn to minimize the battery life impact of downloads a

Android开发艺术探索——第七章:Android动画深入分析

Android开发艺术探索--第七章:Android动画深入分析 Android的动画可以分成三种,view动画,帧动画,还有属性动画,其实帧动画也是属于view动画的一种,,只不过他和传统的平移之类的动画不太一样的是表现形式上有点不一样,view动画是通过对场景的不断图像交换而产生的动画效果,而帧动画就是播放一大段图片,很显然,图片多了会OOM,属性动画通过动态的改变对象的属性达到动画效果,也是api11的新特性,在低版本无法使用属性动画,但是我们依旧有一些兼容库,OK,我们还是继续来看下详细

《Android深度探索》第五章心得体会

<Android深度探索>第五章讲的是搭建S3C6410开发板的测试环境.S3C6410开发板是由三星公司生产的一款开发板产品,具有许多优点.本书的研究就是基于这块开发板的. 搭建环境需要先安装串口调试工具,然后烧入Android系统. 1. 安装串口调试工具:minicom, 第1步:输入命令 insmod | grep usbserial命令检测当前系统是否支持USB转串口: 第2步:输入命令apt-get install minicom命令安装minicom: 第3步:输入minicom

MiS603开发板 第十五章 MCB DDR3内存测试

作者:MiS603开发团队 日期:20150911 公司:南京米联电子科技有限公司 论坛:www.osrc.cn 网址:www.milinker.com 网店:http://osrc.taobao.com EAT博客:http://blog.chinaaet.com/whilebreak 博客园:http://www.cnblogs.com/milinker/ MiS603开发板 第十五章 MCB DDR3内存测试 15.1 DDR3存储器模块及其测试 图像算法硬件最关键的一部分就是内存,内存保

【视频】零基础学Android开发:蓝牙聊天室APP(四)

零基础学Android开发:蓝牙聊天室APP第四讲 4.1 ListView控件的使用 4.2 BaseAdapter详解 4.3 ListView分布与滚动事件 4.4 ListView事件监听器:OnItemClickedListener 在线收看:http://www.3g-edu.org/news/video026.htm 视频下载:http://pan.baidu.com/s/1jGkjDGE

Git帮助文档阅读笔记----第二章-第四--节远程仓库的使用

管理这些远程仓库,以便推送或拉取数据 添加远程库 移除废弃的远程库 管理各式远程库分支 定义是否跟踪分支 查看当前的远程库 可以用 git remote 命令,它会列出每个远程库的简短名字 也可以加上 -v 选项(译注:此为 --verbose 的简写,取首字母),显示对应的克隆地址: 如果有多个远程仓库,此命令将全部列出.比如在我的 Grit 项目中,可以看到: 添加远程仓库 要添加一个新的远程仓库,可以指定一个简单的名字,以便将来引用,运行 git remote add [shortname

软件构造 第七章第四节 调试

第七章第四节 调试 [bug的常见类型] 数学bug:例如 零除法,算术溢出 逻辑bug:例如 无线循环和无限递归 源头bug:例如 使用了为被定义的变量.资源泄漏,其中有限的系统资源如内存或文件句柄通过重复分配耗尽而不释放.缓冲区溢出,其中程序试图将数据存储在分配存储的末尾. 团队工程bug:例如 评论过时或者评论错误.文件与实际产品的区别 ## 调试的基本过程 Debug是测试的后续步骤:测试发现问题,debug消除问题:当防御式编程和测试都无法挡住bug时,我们就必须进行debug了: D

《android深入探索》第五章心得

看了本书第五章,我了解到了: 使用开发板的原因: 是学习嵌入式技术的主要设备. arm的开发板可基于X86架构的PC在CPU指令及二进制指令格式上都有所不同,且若linux驱动要访问硬件(LCD.Wifi.蓝牙等),并且这些硬件在PC上很难进行模拟,所以就要在带有这些硬件的开发板上进行调试和测试. 与手机类似,比手机更容易安装嵌入式系统,有很多扩展的端口,容易开发定制硬件. S3C6410开发板:三星公司推出的一款低功耗.高性价比的RISC精简指令集处理器,基于ARM11内核,提供了优化的2.5