android设备休眠

从上面的链接里面找到了一些资料:html

若是一开始就对Android手机的硬件架构有必定的了解,设计出的应用程序一般不会成为待机电池杀手,而要设计出正确的通讯机制与通讯协议也并不困难。但若是不去了解而盲目设计,可就没准了。java

首先Android手机有两个处理器,一个叫Application Processor(AP),一个叫Baseband Processor(BP)。AP是ARM架构的处理器,用于运行Linux+Android系统;BP用于运行实时操做系统(RTOS),通信协议栈运行于BP的RTOS之上。非通话时间,BP的能耗基本上在5mA左右,而AP只要处于非休眠状态,能耗至少在50mA以上,执行图形运算时会更高。另外LCD工做时功耗在100mA左右,WIFI也在100mA左右。通常手机待机时,AP、LCD、WIFI均进入休眠状态,这时Android中应用程序的代码也会中止执行。android

Android为了确保应用程序中关键代码的正确执行,提供了Wake Lock的API,使得应用程序有权限经过代码阻止AP进入休眠状态。但若是不领会Android设计者的意图而滥用Wake Lock API,为了自身程序在后台的正常工做而长时间阻止AP进入休眠状态,就会成为待机电池杀手。好比前段时间的某应用,好比如今仍然干着这事的某应用。服务器

首先,彻底不必担忧AP休眠会致使收不到消息推送。通信协议栈运行于BP,一旦收到数据包,BP会将AP唤醒,唤醒的时间足够AP执行代码完成对收到的数据包的处理过程。其它的如Connectivity事件触发时AP一样会被唤醒。那么惟一的问题就是程序如何执行向服务器发送心跳包的逻辑。你显然不能靠AP来作心跳计时。Android提供的Alarm Manager就是来解决这个问题的。Alarm应该是BP计时(或其它某个带石英钟的芯片,不太肯定,但绝对不是AP),触发时唤醒AP执行程序代码。那么Wake Lock API有啥用呢?好比心跳包从请求到应答,好比断线重连从新登录这些关键逻辑的执行过程,就须要Wake Lock来保护。而一旦一个关键逻辑执行成功,就应该当即释放掉Wake Lock了。两次心跳请求间隔5到10分钟,基本不会怎么耗电。除非网络不稳定,频繁断线重连,那种状况办法很少。微信

网上有说使用AlarmManager,由于AlarmManager 是Android 系统封装的用于管理 RTC 的模块,RTC (Real Time Clock) 是一个独立的硬件时钟,能够在 CPU 休眠时正常运行,在预设的时间到达时,经过中断唤醒 CPU。网络

 

 

移动互联网应用现状

由于手机平台自己、电量、网络流量的限制,移动互联网应用在设计上跟传统 PC 上的应用很大不同,须要根据手机自己的特色,尽可能的节省电量和流量,同时又要尽量的保证数据能及时到达客户端。架构

为了解决数据同步的问题,在手机平台上,经常使用的方法有2种。一种是定时去服务器上查询数据,也叫Polling,还有一种手机跟服务器之间维护一个 TCP 长链接,当服务器有数据时,实时推送到客户端,也就是咱们说的 Push。app

从耗费的电量、流量和数据送达的及时性来讲,Push 都会有明显的优点,但 Push 的实现和维护成本相对较高。在移动无线网络下维护长链接,相对也有一些技术上的难度。本文试图给你们介绍一下咱们极光推送在 Android 平台上是如何维护长链接。less

移动无线网络的特色

由于 IP v4 的 IP 量有限,运营商分配给手机终端的 IP 是运营商内网的 IP,手机要链接 Internet,就须要经过运营商的网关作一个网络地址转换(Network Address Translation,NAT)。简单的说运营商的网关须要维护一个外网 IP、端口到内网 IP、端口的对应关系,以确保内网的手机能够跟 Internet 的服务器通信。异步

http://www.cisco.com/en/US/i/100001-200000/110001-120000/119001-120000/119935.jpg

图片源自 cisco.com. 

NAT 功能由图中的 GGSN 模块实现。

大部分移动无线网络运营商都在链路一段时间没有数据通信时,会淘汰 NAT 表中的对应项,形成链路中断。

Android 平台上长链接的实现

为了避免让 NAT 表失效,咱们须要定时的发心跳,以刷新 NAT 表项,避免被淘汰。

Android 上定时运行任务经常使用的方法有2种,一种方法用 Timer,另外一种是AlarmManager。

Timer

Android 的 Timer 类能够用来计划须要循环执行的任务,Timer 的问题是它须要用 WakeLock 让 CPU 保持唤醒状态,这样会大量消耗手机电量,大大减短手机待机时间。这种方式不能知足咱们的需求。

AlarmManager

AlarmManager 是 Android 系统封装的用于管理 RTC 的模块,RTC (Real Time Clock) 是一个独立的硬件时钟,能够在 CPU 休眠时正常运行,在预设的时间到达时,经过中断唤醒 CPU。

这意味着,若是咱们用 AlarmManager 来定时执行任务,CPU 能够正常的休眠,只有在须要运行任务时醒来一段很短的时间。极光推送的 Android SDK 就是基于这种技术实现的。

服务器设计

当有大量的手机终端须要与服务器维持长链接时,对服务器的设计会是一个很大的挑战。

假设一台服务器维护10万个长链接,当有1000万用户量时,须要有多达100台的服务器来维护这些用户的长链接,这里还不算用于作备份的服务器,这将会是一个巨大的成本问题。那就须要咱们尽量提升单台服务器接入用户的量,也就是业界已经讨论好久了的 C10K 问题。

C2000K

针对这个问题,咱们专门成立了一个项目,命名为C2000K,顾名思义,咱们的目标是单机维持200万个长链接。最终咱们采用了多消息循环、异步非阻塞的模型,在一台双核、24G内存的服务器上,实现峰值维持超过300万个长链接。

 

http://docs.jpush.cn/pages/viewpage.action?pageId=3309821

 

后记

稳定维护长链接是推送平台的一个基础,极光推送团队将会在这方面长期投入,以保证用户能有效的节省电量、流量,同时数据能实时送达。

以上是极光推送官方的文章,可是看了以后难免有几个疑问。

 

1)他们号称最高峰值能够达到300W的长链接,可是活跃连接的处理最高是多少呢?

2)消息的平均长度和限制各是多少?

3)消息的及时性怎么样,延时是多少?

4)不知道如今,极光推送的用户大概有多少,因此这个峰值是在生产环境,仍是测试环境的数值?

5)我想不通的是为何,客户端要用AlarmManager来作推送消息的获取?这个消息获取还及时吗?鄙人结识android也有N载。

6)我感兴趣的是,不是极光方案一个月推送了几百万条数据,而是几秒钟或者一分钟能够处理多少。

 

Android 消息推送方案

  当咱们开发须要与服务器交互的应用程序时,基本上都须要获取服务器端的数据。要获取服务器上不定时更新的信息,通常来讲有两种方法:第一种是客户端使用pull(拉)的方式,隔一段时间就去服务器上获取一下信息,看是否有更新的信息出现;第二种就是服务器使用push(推送)的方式,当服务器端有更新,则将最新的信息push到客户端上,如此以来,客户端就能自动地接收到消息。

  虽然pull和push两种方式都能实现获取服务器端数据更新的功能,但pull方式的弊端很明显:费流量、费电,须要咱们的程序不停地去监测服务器端的更新。

  首先能够来了解一下iOS和Android平台的推送机制:

  iOS 系统的推送(APNS,即 Apple Push Notification Service)依托一个或几个系统常驻进程运做,是全局的(接管全部应用的消息推送),因此可看做是独立于应用以外,并且是设备和苹果服务器之间的通信,而非应用的提供商服务器。好比腾讯 QQ 的服务器(Provider)会给苹果公司对应的服务器(APNs)发出通知,而后再中转传送到你的设备(Devices)之上。当你接收到通知,打开应用,才开始从腾讯服务器接收数据,跟你以前看到通知里内容同样,但倒是经由两个不一样的通道而来。

  Android的推送有两种形式,一种是后台Service,一种是GCM

  不过这里要指出的是,Android的这种形式和传统电脑仍是有区别的,电脑的后台是保持程序进程在后台运行,而Android是在程序后台Service区域添加一个新的程序专门接收数据。

  要说的话,Android的后台推送机制更加复杂,可是由于可操控部分更多,加上GCM是在2.X以后才加上的并且有可能在系统中并不存在,因此不少软件都是使用Service这种形式。

  本质上,APNs 与 GCM 是相似的技术实现原理:即系统层有一个常驻的 TCP 长链接,一直保持的长链接,即便手机休眠的时候也在保持的长链接。这里对于大部分人来讲,最不理解的就是,休眠时候都保持在那里的 TCP 长链接,不会耗电很厉害么

  答案是:不会。这是手机的设计来作到的。TCP长链接有个心跳的时间,在国外能够很长好比30分钟,在国内则由于网络环境复杂通常10分钟。客户端发起的心跳,会短暂地消耗手机电能,但在这个心跳间隔期间,则消耗电能是不多的。当在心跳期间服务器端有推送信息过来时,客户端能够收到并作处理。

  这里有篇文章以 Android 为例作原理解释:

  /jpush_wireless_push_principle/

  极光推送技术原理:无线网络长链接

  再说 APNs 的设计成功处。

  iOS 为了真正地为用户体验负责,不容许应用在后台活动。有了这个限制,可是对于终端设备,应用又是有必要“通知”到达用户的,随时与用户主动沟通起来的(典型的如聊天应用)。

  这就是 APNs 的逻辑所在:iOS 本身作个长驻后台保持链接。全部应用,有必要(申请)而且被容许(用户能够改设置)的话,能够经过 APNs 中转到达用户。

  Android 由于后台能够长驻,尤为是国内的 Android 的手机上 Google自家的推送服务 GCM 处于基本不可用的状态。因此,各App各显神通。聊天类应用的话,大多数直接借用 XMPP 规范里的一些成果。少许如微信有IM底子的,本身开发协议。这些在实现原理上与 APNs / GCM 没有本质的区别,但有必定的技术门槛。而大多数广泛应用,要使用推送的话,则使用轮询的方式简单实现。

  其实,国外如 Urban Airship 本身实现了 Android 上的第三方提供的推送平台。国内如极光推送也实现了第三方的推送平台(技术与微信、GCM、APNs相似)。理论上,若是一个 Android 设备上多款应用都使用极光推送这种第三方推送平台的话,也能够如 APNs 同样达到节省电量、流量消耗的效果。

  另可参考Android实现推送方式解决方案

 

 

在开发Android的过程当中,咱们常常用到的WIFI在休眠状况下默认是会不链接的,这个时候当咱们须要保持链接时,该如何解决

        很多人说能够在系统设置的WIFI高级选项中将链接设为休眠保持链接,这个办法的确可行,对于开发者来讲很容易办到,可是对于用户来讲他们通常不会知道这么设置,这个时候该怎么办呢?可使用以下代码解决

 

 

[java]
public void WifiNeverDormancy(Context mContext) 

    ContentResolver resolver = mContext.getContentResolver(); 
 
   int value = Settings.System.getInt(resolver, Settings.System.WIFI_SLEEP_POLICY,  Settings.System.WIFI_SLEEP_POLICY_DEFAULT); 
   final SharedPreferences prefs=PreferenceManager.getDefaultSharedPreferences(mContext); 
    
   Editor editor = prefs.edit(); 
   editor.putInt(mContext.getString(R.string.wifi_sleep_policy_default), value);  
 
   editor.commit(); 
   if(Settings.System.WIFI_SLEEP_POLICY_NEVER != value) 
   { 
      Settings.System.putInt(resolver, Settings.System.WIFI_SLEEP_POLICY, Settings.System.WIFI_SLEEP_POLICY_NEVER); 
 
   } 
   System.out.println("wifi value:"+value); 

 public void WifiNeverDormancy(Context mContext)
 {
  ContentResolver resolver = mContext.getContentResolver();

    int value = Settings.System.getInt(resolver, Settings.System.WIFI_SLEEP_POLICY,  Settings.System.WIFI_SLEEP_POLICY_DEFAULT);
    final SharedPreferences prefs=PreferenceManager.getDefaultSharedPreferences(mContext);
   
    Editor editor = prefs.edit();
    editor.putInt(mContext.getString(R.string.wifi_sleep_policy_default), value);

    editor.commit();
    if(Settings.System.WIFI_SLEEP_POLICY_NEVER != value)
    {
       Settings.System.putInt(resolver, Settings.System.WIFI_SLEEP_POLICY, Settings.System.WIFI_SLEEP_POLICY_NEVER);

    }
    System.out.println("wifi value:"+value);
 }上面这个函数,会自动修改咱们WIFI设置中的高级选项,将其设置为一直保持链接。不用使用其余控件就能够解决。

须要注意的是此函数在调用时必须如今AndroidManifest.xml中声明权限

 <uses-permission android:name="android.permission.WRITE_SETTINGS"/>

 

 

 

转】Android设置手机WIFI休眠策略

在开发Android应用中,有很大一部分app是要求手机一直处于网络环境中的。在Android 设置--> WLAN -->点击菜单键 选择 高级 -->休眠状态下保持WLAN链接的下拉列表{始终、仅限充电时、从不(会增长数据流量)}这个设置项中,不少用户并不知道这个选项的存在,若是设置不为始终,那么咱们锁屏休眠后,程序将会处于无网络状态,相应的app用户会一直处于离线模式,那么带来的效果可想而知。

那么咱们开发中,应对这种状况,咱们能够在程序首先开启时,读取这个值,保存起来,待程序退出时,将原先保存的值还原,这样能够很好的解决上述这个问题。

在Android API中这样描述:

public static final String WIFI_SLEEP_POLICY
Since: API Level 3

The policy for deciding when Wi-Fi should go to sleep (which will in turn switch to using the mobile data as an Internet connection).

Set to one of WIFI_SLEEP_POLICY_DEFAULT, WIFI_SLEEP_POLICY_NEVER_WHILE_PLUGGED, or WIFI_SLEEP_POLICY_NEVER.

Constant Value:"wifi_sleep_policy"
 
那么咱们在开启应用时,首先取出这个值,上代码:
private void setWifiDormancy()
{
   int value = Settings.System.getInt(getContentResolver(), Settings.System.WIFI_SLEEP_POLICY,  Settings.System.WIFI_SLEEP_POLICY_DEFAULT);
   final SharedPreferences prefs = getSharedPreferences(getString(R.string.wifi_sleep_policy), Context.MODE_PRIVATE);
   Editor editor = prefs.edit();
   editor.putInt(getString(R.string.wifi_sleep_policy_default), value); 
   editor.commit();
   if(Settings.System.WIFI_SLEEP_POLICY_NEVER != value)
   {
      Settings.System.putInt(getContentResolver(), Settings.System.WIFI_SLEEP_POLICY, WIFI_SLEEP_POLICY_NEVER);
   }
}
 
在应用退出咱们需将这个设置的值还原:
private void restoreWifiDormancy()
{
   final SharedPreferences prefs = getSharedPreferences(getString(R.string.wifi_sleep_policy), Context.MODE_PRIVATE);
   int defaultPolicy = prefs.getInt(getString(R.string.wifi_sleep_policy_default), Settings.System.WIFI_SLEEP_POLICY_DEFAULT);
   Settings.System.putInt(getContentResolver(), Settings.System.WIFI_SLEEP_POLICY, defaultPolicy);
}
 
这样初始设置,退出还原咱们可让应用一直处于wifi模式下(不过前提是有wifi网络哦)。

 

from: http://blog.sina.com.cn/s/blog_a85b30ff0101ahzd.html

 
 

Android 关于休眠的几个坑点

首先看一下Android Powermanager Class Overview,对Android的几种不一样的休眠模式有个大体了解。

若是不进行特别的设置,Android会在必定时间后屏幕变暗,在屏幕变暗后必定时间内,约几分钟,CPU也会休眠,大多数的程序都会中止运行,从而节省电量。但你能够在代码中经过对Powmanager API的调用来设置不一样的休眠模式。

Flag Value         CPU Screen Keyboard
PARTIAL_WAKE_LOCK On* Off Off
SCREEN_DIM_WAKE_LOCK On Dim Off
SCREEN_BRIGHT_WAKE_LOCK On Bright Off
FULL_WAKE_LOCK         On Bright Bright

如上表,最高等级的休眠是屏幕,键盘等,cpu都所有休眠。能够设置不一样的模式,让其产生不一样的休眠,好比让cpu保持运行。
设置代码以下:

 
  
  1. PowerManagerpm =(PowerManager)getSystemService(Context.POWER_SERVICE);

  2. PowerManager.WakeLockwl =pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK,"My Tag");

  3. wl.acquire();

  4. ..screen will stay on during thissection..

  5. wl.release();

 
  

我曾经遇到的几个坑点及解决:

1.向服务器轮询的代码不执行。

曾经作一个应用,利用Timer和TimerTask,来设置对服务器进行定时的轮询,可是发现机器在某段时间后,轮询就再也不进行了。查了好久才发 现是休眠形成的。后来解决的办法是,利用系统的AlarmService来执行轮询。由于虽然系统让机器休眠,节省电量,但并非彻底的关机,系统有一部 分优先级很高的程序仍是在执行的,好比闹钟,利用AlarmService能够定时启动本身的程序,让cpu启动,执行完毕再休眠。

2.后台长链接断开。

最近遇到的问题。利用Socket长链接实现QQ相似的聊天功能,发如今屏幕熄灭一段时间后,Socket就被断开。屏幕开启的时候需进行重连,但 每次看Log的时候又发现网络是连接的,后来才发现是cpu休眠致使连接被断开,当你插上数据线看log的时候,网络cpu恢复,一看网络确实是连接的, 坑。最后使用了PARTIAL_WAKE_LOCK,保持CPU不休眠。

3.调试时是不会休眠的。让我很是郁闷的是,在调试2的时候,就发现,有时Socket会断开,有时不会断开,后来才搞明白,由于我有时是插着数据线进行调试,有时拔掉数据线,这 时Android的休眠状态是不同的。并且不一样的机器也有不一样的表现,好比有的机器,插着数据线就会充电,有的不会,有的机器的设置的充电时屏幕不变暗 等等,把本身都搞晕了。其实搞明白这个休眠机制,一切都好说了。

相关文章
相关标签/搜索