您的位置:首页 > 移动开发 > Android开发

Android-电量优化

2016-05-05 15:57 330 查看
Android手机和iphone相比较起来,运行以及耗电都没有iphone体验更好。主要是Android的多任务机制问题。最直观的就是很多Android手机出厂就会带上清理垃圾,清理内存的软件。会有一键清理释放内存功能。但是在iphone上你是看不到的。

Android:为了提高手机运行速度或者是有强迫症的,就会经常一键清理。99%的用户手机上几乎都安装一个优化软件或原厂或第三方。没有使用任何优化软件的用户一夜待机手机耗电就会很高。
Iphone:不用总去杀进程你也不会感觉到卡,正常来说不用安装优化软件(如果你从用手机开始就是iphone的话就更应该是这样,几乎iphone里有优化软件的都是从android手机过来的),夜间耗电量也没有android那么高

为什么会这样呢?

Android的机制是退出但不关闭,当Android应用程序退出时,并不清理其所占的内存,Linux内核也相应的继续存在,这就导致如果开的程序多,那么手机就会变卡,尤其是内存小的手机。Android手机有很多权限可以通过各种事件唤醒手机,如:信号变化,网络切换。保留进程运行状态,假如iphone的后台是活死人状态那么Android后台就是可以自由活动的活人,甚至会自己把别的程序弄活,也就是唤醒其他app,然后在你的手机里happy。还有由于网络延迟问题和手机厂商的各种定制,导致想做推送服务的app都使用自家的服务器,而不能使用谷歌的推送,导致app需要和服务器保持相对较多的连接,也很消耗资源。
而iphone会回收任务内存,会统一的走系统(苹果)的推送机制,会限制后台活动。。。

这些都是普通开发者无法改变的事情,想改善就要在自己技术上下功夫。
耗电问题:用户还是有很多时间使用234G网络的,使用234G时候耗电量就会高于wifi下。移动网络耗电原因是这样:

手机在不传输数据的情况下一般处于空闲状态(Idle),当有发送数据需求时必须向控制平台发送申请。只有将手机切换到Active状态,也就是高耗能模式下才能进行通信。这一切换过程在4G网络下需要花费100ms的时间。通信完成后,手机不会一直处于高耗能模式下等待数据传输,它会切换到低耗能模式(Short
sleep)。如果手机处于低耗能模式时接到数据发送请求,那么它又会切换到高耗能模式来发送数据。在频繁的数据请求中,它会在低耗能模式和高耗能模式不断的切换,而在不发送数据时,在10s后会再次进入空闲模式下。它会周期性的切换模式来确保资源的有效利用。看张网上拿来的图


移动网络只有在处于DCH(高耗能模式)和
FACH(低耗能模式)下才会消耗手机电量。从上图可以看出,一次耗能模式切换大概需要花费10s,而且不管你传输的数据大小,它都会触发一次耗电周期,消耗10s的电量。
解决办法也就可以看出来了,一次请求无论时间内传输多少数据,都会触发一次10s的耗电,所以可以适当的合并请求,优化心跳,心跳时候有几个重要参数,时间间隔,重连超时时间,重连次数,避免过渡频繁的心跳,如果手机连接不上也不能无止境的重连那会很快消耗掉电量。
另外可以试试延迟拉去或者是时间戳:

以即时通讯类app为例,用户登录时一般需要拉哪几类数据?列表,详情,朋友圈。
用户在登录后有些数据是一定用到的,如好友列表。有些就是用不到的,如好友详情。那么就可以登录时候只加载好友列表,当用户主动查询详情时候再做拉取,这样可以节省流量也会加快登录速度。
时间戳什么用呢?用户登录时候,本地数据是不能直接使用的,因为不确定是否是最新数据,那么就可以再登录时候只拉去服务器时间戳和本地的进行对比,如果是最新的数据那就直接使用,可以避免重新拉取。因为好友列表变化不是那么频繁的事情,所有用时间戳是非常有效的办法。节约流量,加快登录时间,节约电量,用户体验更佳。但是同样也有缺点存在,假设你有10个好友,没有用时间戳时候每次登录都要向服务器拉取这10个好友,有了时间戳当没有好友增加时候是最佳的,当有好友增加,就要拉取服务器时间戳和本地时间戳做对比,结果发现增加了好友,那么就再向服务器拉取最新数据。相比没有时间戳多了一次拉取时间戳的网络请求。
那么可以使用时间戳的同时减少网络交互次数呢?当然可以:客户端对时间戳的使用,往往采取“客户端拉取时间戳”+“客户端比对时间戳”+“客户端再次拉取差异数据”的方式进行,“时间戳比对”的的CPU计算发生在客户端,其实,这个计算可以转嫁到服务器,步骤为:(1)客户端上传100个好友的时间戳(2)服务端收到客户端上传的时间戳,与最新时间戳对比,找出差异,假设有10个好友的信息发生了变化,服务端可以直接将有差异的10个好友的数据返回;客户端少了一次网络请求,对比时间戳的计算需要在服务器端进行。

简单的说耗电主要发生在:

1、 大数据量的传输。2、 不停的在网络间切换。3、 解析大量的文本数据。

如果在需要网络连接的程序中,首先检查网络连接是否正常,如果没有网络连接,那么就不需要执行相应的程序。
使用效率高的数据格式和解析方法,目前主流的数据格式,使用树形解析(如DOM)和流的方式解析(SAX),两种方式中使用流的方式解析效率要高一些,因为DOM解析是在对整个文档读取完后,再根据节点层次等再组织起来。而流的方式是边读取数据边解析,数据读取完后,解析也就完了。
进行大数据量下载时,尽量使用GZIP方式下载。HttpGet request = new HttpGet("http://example.com/gzipcontent");HttpResponse resp = new DefaultHttpClient().execute(request);HttpEntity entity = response.getEntity();InputStream
compressed = entity.getContent();InputStream rawData = new GZIPInputStream(compressed);能节约流量。
很多人开发的程序后台都会一个service不停的去服务器上更新数据,在不更新数据的时候就让它sleep,这种方式是非常耗电的,通常情况下,我们可以使用AlarmManager来定时启动服务。

从 Android6.0 开始(API-23以上), Android 提供了两种省电延长电池寿命的功能: Doze 和App
Standby

1. 设备进入 Doze 模式前提:

用户不操作设备一段时间

屏幕关闭

设备未连接电源充电

Doze有五种状态:

ACTIVE – 设备在使用中,或者连接着电源。
INACTIVE – 设备已经从ACTIVE状态中出来一段时间了(使用者关闭了屏幕或者拔掉了电源)。
IDLE_PENDING – 请留意,我们将进入idle mode。
IDLE – 设备进入idle mode。
IDLE_MAINTENANCE – 应用窗口已经打开去做处理。



图中的30秒是Doze 期间提供间隔一小段时间( 30s )供应用程序使用网络和处理挂起的活动。但是随着系统进入 Doze 模式后,系统会隔一段时间处理正在挂起的任务,随着时间推移,后面间隔的时间会越来越长,以此来减少电量消耗。

Doze 模式下应用程序有什么变化?:

系统试图通过限制应用程序访问网络和 CPU 密集型服务节省电池;
防止应用程序访问网络,推延应用程序的工作,同步,和标准的警报;
系统定期提供一个短暂的时间(30s)让应用程序完成延迟的工作活动,在这个时间段里,系统将提供维持性窗口应用程序访问网络,运行在等待的同步,工作,和报警等活动。



如果应用不在白名单,系统灭屏经过大约一小时后,上层应用wake lock,alarm,还有网络链接都会失效,系统将不扫描热点 WIFI,同步工作将被禁止,不允许 JobScheduler 进行任务调度,除非你是白名单应用,检测应用程序是否存在白名单 list 里面,可使用 PowerManager 的isIgnoringBatteryOptimizations() 方法。
Doze 影响到 AlarmManager 闹钟和定时器管理活动,在 Android6.0 引入了两个新方法setAndAllowWhileIdle() 和 setExactAndAllowWhileIdle() ,调用两个方法可以在 Doze 模式下让系统响应定时任务;
Doze 模式下限制了网络的连接,如果应用程序依赖于实时信息,那么这个将影响App 的体验。那么你需要使用 Google
Cloud Messaging (GCM) 谷歌云消息,但是由于网络状况,服务器又在国外延迟应该比较高,还有国内第三方手机厂商如华为、小米、三星,定制的 Rom 也将使用定制的推送消息机制。可能google的推送不是那么好用啊。

什么是GCM?
Google Cloud Messaging(GCM) 是云端到设备的服务,可以支持实时在服务端和 Android 应用程序之间的消息传递。

GCM 提供了一个持久连接到服务器的链接,让需要将实时消息传递到应用的程序可以共享此链接。这个共享链接显著优化了电量的消耗,使其不必让多个应用程序各位维护自己单独的持久链接而使电池迅速耗尽电量。

GCM 消息拥有高优先级,不影响 Doze 模式,且不会不影响其他应用程序的状态。

以下来 自GCM 官方解释:

一个 GCM 实现包括谷歌连接服务器,在你的环境中通过 HTTP 或 XMPP 协议的连接服务器进行交互的应用程序服务器和客户端应用程序。

生命周期流程:

注册启用 GCM: 客户端应用程序注册为接收消息。

发送和接收下行消息:

发送一个消息, 该应用程序服务器发送信息到客户端应用程序:

1. 该应用程序服务器发送消息给 GCM 连接服务器;

2. 当设备处于脱机状态,该 GCM 连接服务器入队并存储消息;

3. 当设备联机时, GCM 连接服务器将邮件发送到该设备;

4. 在设备上,所述客户端应用程序根据该特定平台实现接收该消息。

接收消息,客户端应用程序收到一条消息从 GCM 连接服务器。

发送和接收上游的消息: 如果您使用的是此功能只提供 XMPP 连接服务器 。

发送一个消息, 客户端应用程序将消息发送到应用服务器:

1. 在设备上,客户端应用程序将消息发送到 XMPP 连接 server;

2. 如果该服务器已断开连接,该 XMPP 服务器连接入队并存储信息;

3. 当应用程序服务器重新连接后, XMPP 连接服务器将邮件发送到应用程序服务器。

接收消息, 一个应用服务器从 XMPP 连接服务器接收邮件,然后执行以下操作:

1 、解析消息头,以验证客户端应用程序发送的信息;

2 、发送“确认”的 XMPP 连接服务器以确认收到该消息;

3 、任选解析该消息有效载荷,由客户端应用程序所定义的。

除了 GCM , Android6.0 及更高版本还提供了 Doze 模式白名单列表,通过设置应用程序进入白名单列表可逃脱 Doze 模式的各种限制。用户也可手动设置应用程序进入白名单列表里面,路径为:设置 > 电池 > 电池优化白名单


客户端使用方法:

1 . App 程序可发送 action 为ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS 的 intent 引导用户进入设置界面将应用程序设置进白名单列表里。

2. 应用程序还可以使用 AREQUEST_IGNORE_BATTERY_OPTIMIZATIONS 权限来触发一个系统对话来让用户添加到白名单里,而无需进入设置界面去设置。

不过估计天朝会想办法通过so绕过doze

当然,官方也提供用户把你的 App 移除电池优化白名单的选项。这个白名单也会被Android M 的另一个新特性 App Standby 使用,所以用户只能简单的进行控制,也就是说设备并不会完全相信这个白名单。


App Standby

当用户不触摸使用应用程序一段时间时,该应用程序处于 App Standby 状态,系统将把该 App 标志为空闲状态。除非触发以下任意条件,应用程序将退出 App Standby状态:

1. 用户主动启动该 App;

2. 该 App 当前有一个前台进程(或包含一个活动的前台服务,或被另一个 activity或前台 service 使用);

3 . App 生成一个用户所能在锁屏或通知托盘看到的 Notification, 而当用户设备插入电源时,系统将会释放 App 的待机状态,允许他们自由的连接网络及其执行未完成的工作和同步。如果设备空闲很长一段时间,系统将允许空闲 App 一天一次访问网络。

Doze 和 App Standby 的区别:

Doze 模式需要屏幕关闭(通常晚上睡觉或长时间屏幕关闭才会进入),而 App Standby 不需要屏幕关闭, App 进入后台一段时间也会受到连接网络等限制。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: