需求分析: 在项目中,有这么一个功能点,app进程中,需要实现一个定时任务,只要设备处于开机状态,每隔半个小时,就需要定时向服务器上传一次位置信息,并且只要是有网络和获取到GPS信号,进程不能死,如果进程死掉了,需要自动重启。对该点进行细分梳理,包含如下几个小功能点:
1.进程能够实现开机启动。
2.进程需要一直存活,并且能够自动重启。
3.需要定时(30分钟)一次,向server端上报信息。
针对以上三个功能点,第1和2点,实现起来,都不难,唯独第三点:我这里提供如下解决方案:
方案一. 死循环中,使用sleep方法: for(;;) Tread.sleep 30分钟
方案二. timer机制 timerTask 30分钟一次
最终方案三.AlarmManager进行精准定时
1.进程能够实现开机启动。
2.进程需要一直存活,并且能够自动重启。
3.需要定时(30分钟)一次,向server端上报信息。
针对以上三个功能点,第1和2点,实现起来,都不难,唯独第三点:我这里提供如下解决方案:
方案一. 死循环中,使用sleep方法: for(;;) Tread.sleep 30分钟
方案二. timer机制 timerTask 30分钟一次
最终方案三.AlarmManager进行精准定时
方案一和方案二的定时方案不准,主要原因是sleep和timerTask的内部线程运行的时间。在thread运行时,CPU才开始计算时间,当线程挂起,CPU没有将时间片交给该线程,就没有计算时间。实际使用中,app在后台运行越长,误差就越大。
AlarmManager需要处理的问题:
Q1:进程死掉后,AlarmManager是否还有效果?是否需要使用自动重启的service来重启进程?
Q2:设备reboot(重启)后,设置的AlarmManager是否还有效?
Q3:重复set相同的alarm,是否会影响AlarmManager的定时机制?
阅读关于Alarm机制源码(参考: Android 4.0 Alarm机制浅析)后发现,在设备reboot后,为了确保AlarmManager的setInexactRepeating还有效,必须在设备接收到ACTION_BOOT_COMPLETED事件时,重新进行set alarm。精准的定时方案大致如下:
1)注册广播,接收系统ACTION_BOOT_COMPLETED事件时,进行set alarm,进行精准定时任务
2)在alarm中启动service,service中实现网络HTTP请