待机后的JPush推送不到的问题
<h1>待机状态下极光推送不到的问题</h1>
<p>@author Penny
@time 2017/03/21</p>
<h2>问题描述</h2>
<p>后视镜在ACC OFF(待机)状态下,极光推送消息不能到达,当ACC ON之后就收到了。</p>
<h2>问题猜想</h2>
<h3>猜想一:</h3>
<p>ACC OFF状态,网络异常所致。</p>
<h3>猜想二:</h3>
<p>ACC OFF 状态下推送的长连接断开</p>
<h2>问题查阅</h2>
<p>[android设备休眠 ](<a href="http://www.cnblogs.com/kobe8/p/3819305.html">http://www.cnblogs.com/kobe8/p/3819305.html</a> "android设备休眠 ")
[JPush推送](<a href="http://www.cnblogs.com/kobe8/p/3819305.html">http://www.cnblogs.com/kobe8/p/3819305.html</a> "JPush推送")
[Android闹铃服务AlarmManager用法深入分析](<a href="http://www.jb51.net/article/90491.htm">http://www.jb51.net/article/90491.htm</a> "Android闹铃服务AlarmManager用法深入分析")</p>
<h2>问题分析</h2>
<h3>第一步: 判断网络状态</h3>
<p>1、使用创建socket的方式
2、外接串口线,使用tupdump抓包,配合wiresharp进行分析</p>
<p>结论 : 最终判定ACC OFF 状态下网络是正常的。</p>
<h3>第二步:判断极光的推送长连接心跳是否正常</h3>
<p>1、采用外接串口线抓log
2、极光团队配合核对log中的心跳记录</p>
<p>调试结果:一段时间之后,心跳出现异常。</p>
<h2>进一步分析</h2>
<h3>系统的休眠策略</h3>
<p>1、系统5分钟唤醒一次
2、系统对唤醒锁wakelock的管理策略
3、系统会对唤醒锁进行清理(前15s可以申请锁,15s后不允许应用再申请锁,系统从唤醒到再次休眠时会清理所有应用的申请锁)</p>
<h3>极光SDK申请锁的处理</h3>
<p>1、极光SDK心跳采用的是AlarmManager方式,系统唤醒时SDK会申请wakelock锁
2、SDK持有唤醒锁使用handler去发送一条message,然后释放锁,处理心跳的事务交给handler去处理</p>
<p>经过对系统的休眠机制、wakelock锁的管理机制和JPush的持锁机制综合分析,
得到初步结论:
1、当系统进入休眠之后,5分钟唤醒一次,唤醒的时候JPush SDK 申请到唤醒锁,然后持锁使用handler
发送一个message,之后就释放了wakelock锁,心跳事务由handler自行处理,但是wakelock被释放之后,
系统很快就进入了休眠,导致心跳事务没有处理完成,心跳异常,导致长连接断开。
2、系统的wakelock管理的计时器不合理,导致sdk出现偶尔申请锁失败,导致心跳异常,然后长连接断开。</p>
<h2>修改问题:</h2>
<p>1、系统修改wakelock锁管理的计时器,原先的计时器不是用于待机时加wakelock。
2、JPush SDK 修改为持锁处理心跳事务,处理完成在释放wakelock锁,确保心跳事务能处理完成系统才待机。</p>