使用 GCM 网络管理工具优化电池使用

本文讲的是使用 GCM 网络管理工具优化电池使用,


通过GCM网络管理工具我们可以注册用于执行网络任务的服务,其中每一个任务都是一件独立的工作。GCM的API帮助进行任务的调度,并让Google Play服务在系统中批量进行网络操作。

其API还有助于简化网络操作模式,比如等待网络连接、进行网络重连与补偿等。总的来说,GCM网络管理工具通过提供一个简洁明快的网络请求调度API来帮助开发者在网络相关的问题上少费心思。

电量和网络操作

在深入GCM与其优势之前,我们先聊一聊与网络请求相关的电池使用问题,这有助于我们认识批量处理网络操作的重要性。

下面是Android通讯模块(radio)的状态机:

这个图还是挺清晰的。我想通过这个图表告诉大家唤醒通讯模块是处理网络连接时最耗电的操作,也就是说,网络操作是电池最大的消耗者。

虽然一个网络操作不可能耗尽电池,但唤醒通讯模块所发送的单个请求数目相当可观。如果网络请求是单独发送的,那么设备就会被持续唤醒,通讯模块也会保持开启状态。设备持续唤醒无法休眠会导致电量大幅消耗。(就如人睡不着觉一样)

下面的示意图说明了一个叫PhotoGallery的图片获取APP的单次网络请求,这个APP也是我们的畅销书Android Programming Book中的一个示例APP。

看起来单次网络操作也没啥。网络模块被唤醒了,但这只是单次请求。

而多次请求的示意图是这样的:

现在我们有了多次网络请求,注意观察网络模块在每次请求时都被唤醒,这会快速消耗电量,让使用者不爽。

在这里我们可以通过批量进行网络操作来优化电池使用,因为这可以减少启动网络模块所消耗的电量。如果网络模块生命周期中最耗电的部分是启动部分,那么我们可以在多次请求中只唤醒一次。如果我们所请求的数据不需要马上获取,而是在未来的某个时间点需要用到,那这种方式还算可行。

批量网络请求的示意图如下:

现在网络模块只会唤醒一次,省了不少电。

有时你的确马上需要用到网络请求的数据,如打游戏或者发短信的情况。这些情况下,还是需要发送单次网络请求,不过要记住这对电池、网络状态和设备重启并无好处。

GcmTaskService

既然我们已经看到了批量进行网络请求对优化电池使用能起到不小的作用,现在让我们在应用中实现GCM网络管理工具。

首先,在build.gradle文件中添加GCM网络管理工具的依赖。

dependencies {
	...
	compile 'com.google.android.gms:play-services-gcm:8.1.0'
	...
}

切记只需依赖Google Play Services的GCM部分,不然你需要依赖所有的Google Play Service,而其中大部分是用不到的方法。

下一步,我们需要在AndroidManifest中声明一个新的Service:

<service android:name=".CustomService"
		android:permission="com.google.android.gms.permission.BIND_NETWORK_TASK_SERVICE"
		android:exported="true">
	<intent-filter>
		<action android:name="com.google.android.gms.gcm.ACTION_TASK_READY"/>
	</intent-filter>
</service>

这里Service的name属性是继承了GcmTaskService的类的类名,GcmTaskService是与GCM网络管理工具交互的核心类。这个Service会处理任务的执行,这里的任务是任何网络工作的一部分。上面代码中action是ACTION_TASK_READY的intent-filter是用于接收GCM中的调度工具所发送的某任务可被执行的通知。

下一步,我们写一个CustomService.java继承GcmTaskService:

public class CustomService extends GcmTaskService {
	...
}

这个类会处理所有执行中的任务。由于继承了GcmTaskService,我们需要在CustomService中重写onRunTask方法。

@Override
public int onRunTask(TaskParams taskParams) {
	Log.i(TAG, "onRunTask");
	switch (taskParams.getTag()) {
		case TAG_TASK_ONEOFF_LOG:
			Log.i(TAG, TAG_TASK_ONEOFF_LOG);
			// 进行逻辑处理
			return GcmNetworkManager.RESULT_SUCCESS;
		case TAG_TASK_PERIODIC_LOG:
			Log.i(TAG, TAG_TASK_PERIODIC_LOG);
			// 进行逻辑处理
			return GcmNetworkManager.RESULT_SUCCESS;
		default:
			return GcmNetworkManager.RESULT_FAILURE;
	}
}

当某一个任务需要执行时,这个方法就会被调用。我们在这里要检测作为参数传入的TaskParams的tag,一个tag单独映射到一个被调度的任务。一般来说我们需要在case代码块中添加网络操作或逻辑操作,但在这里我只打了一个tag。

GcmNetworkManager

现在我们写好了GcmTaskService,我们需要获取到GcmNetworkManager对象的引用,并通过它调度新的任务让刚才写的Service执行。

private GcmNetworkManager mGcmNetworkManager;

@Override
protected void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
	setContentView(R.layout.activity_main);
	...
	mGcmNetworkManager = GcmNetworkManager.getInstance(this);	}

GcmNetworkManager对象是用来调度网络任务的,所以我们可以在onCreate中获取其引用并存为成员变量。或者,你也可以在需要进行网络调度时再获取实例(饿汉)。

任务调度

一个单独的任务相当于一件等待执行的工作,可以分为两种类型:一次性的(OneoffTask)和周期性的(PeriodicTask)。

我们将执行区间(window of execution)传给任务,而后调度工具就会计算确切的执行时间。因为这些任务不需要立即执行,调度器会将许多网络请求捆绑执行来节省电量。

调度器会自己判断网络连接情况、网络任务与网络负荷,如果这些因素都正常,调度工具会等待至给定区间的结束点。

下面是调度一个单次任务的代码:

Task task = new OneoffTask.Builder()
		.setService(CustomService.class)
		.setExecutionWindow(0, 30)
		.setTag(LogService.TAG_TASK_ONEOFF_LOG)
		.setUpdateCurrent(false)
		.setRequiredNetwork(Task.NETWORK_STATE_CONNECTED)
		.setRequiresCharging(false)
		.build();

mGcmNetworkManager.schedule(task);

通过使用Builder模式,我们给定了任务的所有参数:

  • Service: 用于控制任务的确切GcmTaskService。这样我们可以在后面停止它。
  • ExecutionWindow:任务执行的时间区间。第一个参数是最低时间,第二个参数是最高时间(都是以秒为单位)。这个参数是强制的。
  • Tag:这里通过tag来在onRunTask方法中识别哪一个任务正在执行。每个tag都应该是唯一的,长度上限是100位。
  • UpdateCurrent:判断该任务是否要覆盖之前存在的有相同tag的任务。默认情况下这个参数是false,也就是不覆盖。
  • RequiredNetwork:设置一个任务执行所需的网络状态。在这里如果无网络连接,任务就不会被执行。
  • RequiresCharging:任务执行是否需要设备处在充电状态。

都设置好之后,任务就被构建好了,通过GcmNetworkManager实例进行调度,然后在某个时间执行。

而调度一个周期性任务要这样做:

Task task = new PeriodicTask.Builder()
		.setService(CustomService.class)
		.setPeriod(30)
		.setFlex(10)
		.setTag(LogService.TAG_TASK_PERIODIC_LOG)
		.setPersisted(true)
		.build();

mGcmNetworkManager.schedule(task);

和上面的代码区别不大,主要的区别有这些:

  • Period:指定该任务至少要每个时间区间执行一次,时间区间以秒为单位作为参数传入。默认情况下你无法控制任务是在时间区间内的哪个具体时间点执行。这个参数是强制的。
  • Flex:指定该任务需要在距离结束点多长时间之内执行。在这里Period是30,Flex是10,那么任务就会在20-30秒的区间内执行。
  • Persisted:判断该任务在重启过程后是否保留。默认情况下周期性任务的这个参数都是true,而一次性任务没有这个参数。如果是true则需要Receive Boot Completed权限,不然无效。

看到GCM网络管理工具的API有多么的强大了吧?创建和调度代码简直不能更简单。

取消任务

我们已经看到了如何调度任务,所以还需要看一下如何取消任务。正在执行的任务是无法被取消的,但我们可以取消还未被执行的任务。

你可以直接取消给定GcmTaskService的所有任务:

mGcmNetworkManager.cancelAllTasks(CustomService.class);

你也可以通过给出tag和GcmTaskService来取消一个具体任务:

mGcmNetworkManager.cancelTask(
		CustomService.TAG_TASK_PERIODIC_LOG,
		CustomService.class
);

不管怎样,要记住正在执行的任务无法取消。

Google Play服务

使用网络管理工具调度任务的起始点就是刚才使用到的schedule方法,而这需要Google Play服务。为了正常使用其服务,我们需要进行如下检测:

int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if (resultCode == ConnectionResult.SUCCESS) {
	mGcmNetworkManager.schedule(task);
} else {
	// 以其他方式处理task
}

如果Google Play服务不可使用,GcmNetworkManager会静默失效,这就是为什么需要提前检测。

类似地,当Google Play服务或是客户端APP被升级,所有的已调度的任务都会失效。为了避免丢失当前已调度的任务,GcmNetworkManager会调用GcmTaskService(这里是CustomService)的onInitializeTasks()方法。这个方法是用来重新调度任务的,对周期性任务尤其常见。下面是示例:

@Override
public void onInitializeTasks() {
	super.onInitializeTasks();
	// 重新调度已失效的任务
}

总结

我们已经深入研究了一下GCM网络管理工具,以及如何用它来节省电量,优化网络表现,并使用Task进行批量工作。下次你需要在某个时间进行一些网络操作的时候,不妨考虑使用GCM网络管理工具使网络访问更加精简且不失健壮。





原文发布时间为:2016年05月11日


本文来自合作伙伴掘金,了解相关信息可以关注掘金网站。

时间: 2024-11-13 06:55:51

使用 GCM 网络管理工具优化电池使用的相关文章

使用DNS基准测试工具优化你的网络解析

晚上看了网站的<使用DNS基准工具优化域名服务器性能>这篇文章(http://network.51cto.com/art/201103/247326.htm),对测试DNS有了新的认识.可惜文章中没有提供工具的下载地址和使用操作步骤说明. Google了网络上的文章,稍微整理了一下,加点自己的东西.见笑. (DNS Benchmark已经打包在附近里了,大家自己下载.解压.NameBench程序文件太大了,自己去网站下载吧) 谷歌名称工具(NameBench)主页地址:http://code.

四大顶级开源网络管理工具详解

随着网络方案的不断扩展与多元化走势,大量有线及无线设备开始成为网络体系不可或缺的组成部分,用户对网络监控工具的需求也随之持续走高.虽然功能丰富的商业产品比比皆是,但来自开源社区的强大方案仍然对监控工具市场的发展起到巨大的推动作用. 在本系列文章中,我们将一同剖析四款高人气开源产品--Nagios Core 3.5.NetXMS 1.2.7.OpenNMS 1.10.9以及Zenoss Core 4.2.四款产品都已经相当成熟,足以提供与其它企业级同类方案相媲美的综合性监控能力,同时拥有良好的社区

IT管理员得力小助手 分享5款实用网络管理工具

中介交易 http://www.aliyun.com/zixun/aggregation/6858.html">SEO诊断 淘宝客 云主机 技术大厅 网络管理包括对硬件.软件和人力的使用.综合与协调,以便对网络资源进行监视.测试.配置.分析.评价与控制.IT管理人员正对网络管理的要求较高,需要通过工具对网络上的资源进行集中化管理和操作.下面,IDC评述网与大家分享5款实用的网络管理工具. 1.Panoptes Panoptes是一个可伸缩,可扩展的网络和主机的监测工具.包括一个基于Dojo

10大免费网络管理工具

作为一名资深网络工程师,在15年以上的职业生涯中,你可能经历过在各种环境中进行评估,使用了大量的开源网络工具.有些实在是有太多的bug,比如缺乏关键功能或太耗时.你可能也在苦苦寻求着好用的免费网络管理工具,在本文中,我将为您介绍10个免费的网络工具,我相信它们在企业网络的日常管理和故障排除方面会非常有用. 一些IT专业人员完全不理会免费的开源工具,因为他们觉得这些工具相比执行类似职能的商业产品要远远逊色得多.虽然许多商业专有产品增加了额外的功能,使得IT人员更容易使用和维护它们,但是如果开源工具

Android Zipalign工具优化Android APK应用_Android

       生成的Android应用APK文件最好进行优化,因为APK包的本质是一个zip压缩文档,经过优化能使包内未压缩的数据有序的排列,从而减少应用程序运行时的内存消耗.我们可以使用Zipalign工具进行APK优化.        据Android官方网站的说明,Zipalign是一款重要的优化APK应用程序的工具.        多数软件开发商在正式推出其Android应用程序,都使用Zipalign工具优化APK包.但是,仍然有一些应用程序需要我们自己动手进行Zipalign优化,例

选好网络管理工具 “0掉线”也并非不可能

企业网络管理是项并不简单的工作:IT方面必须满足用户对于出色服务质量的期望,这需要IT清楚地了解日益复杂的网络中穿梭的流量.这是一个相当大的挑战.今天企业运营的基础设施.表层以及具体的网络架构都是有线和无线网络的结合,并且包含众多个人和公司配发的终端设备. 传统上,IT部门用分离的工具来管理网络中独立的无线和有线元素.然而,随着时间的推移,这些独立的元素都变得更加一体化.终端用户希望所有的企业资产能够无缝地协同工作,这样他们就可以更快速可靠地访问所有资源.分离的管理控制台无法提供这种整体视觉和即

Android Zipalign工具优化Android APK应用

生成的Android应用APK文件最好进行优化,因为APK包的本质是一个zip压缩文档,经过优化能使包内未压缩的数据有序的排列,从而减少应用程序运行时的内存消耗.我们可以使用Zipalign工具进行APK优化. 据Android官方网站的说明,Zipalign是一款重要的优化APK应用程序的工具. 多数软件开发商在正式推出其Android应用程序,都使用Zipalign工具优化APK包.但是,仍然有一些应用程序需要我们自己动手进行Zipalign优化,例如一些个人开发的软件.一些破解版的软件.

photoshop自定义形状工具绘制电池图标

本教程学习如何用photoshop的自定义形状工具.钢笔工具和图层样式打造高光质感的电池图标,先看效果图. 新建文档950x1024像素,背景白色,建新层填充黑色,添加图层样式. 效果如下. 建新层,画一黑色圆角矩形. 添加图层样式,颜色值请用吸管采样我的截图. 效果如下. 新建图层2,调出形状1选区,选择矩形工具按alt键减选底部,得到上部选区,填充白色. 添加图层样式. 效果如下. 建新层,画下图所示形状,颜色白色. 添加渐变叠加样式,设置请参考上一个渐变叠加样式图. [1] [2]  下一

C++开发的Redis数据导入工具优化_C 语言

背景 使用C++开发了一个Redis数据导入工具 从oracle中将所有表数据导入到redis中: 不是单纯的数据导入,每条oracle中的原有记录,需要经过业务逻辑处理, 并添加索引(redis集合): 工具完成后,性能是个瓶颈: 优化效果 使用了2个样本数据测试: 样本数据a表8763 条记录: b表940279 条记录: 优化前,a表耗时11.417s: 优化后,a表耗时1.883s: 用到的工具 gprof, pstrace,time 使用time工具查看每次执行的耗时,分别包含用户时间