首页 > 代码库 > 安卓笔记20170118

安卓笔记20170118

创建定时任务

Android的Alarm机制。

定时任务也可以使用Java API里提供的Timer类,但它不太适用于那些需要长期在后台运行的定时任务。为了让电池更加耐用,每种手机都会有自己的休眠策略,Android手机就会在长时间不操作的情况下自动让CPU进入到睡眠状态,这就有可能导致Timer中的定时任务无法正常运行。而Alarm则具有唤醒CPU的功能,它可以保证在大多数情况下需要执行定时任务的时候CPU都能正常工作。注意:唤醒CPU和唤醒屏幕不是一个概念。

AlarmManager manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
    long triggerAtTime = SystemClock.elapsedRealtime() + 10 * 1000;
    manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerAtTime, pendingIntent);

set方法接收三个参数
第一个参数是整形参数,用于指定AlarmManager的工作类型,有4种值可选

ELAPSED_REALTIME表示让定时任务的触发时间从系统开机开始算起,但不会唤醒CPU。

ELAPSED_REALTIME_WAKEUP同样表示让定时任务的触发时间从系统开机开始算起,但会唤醒CPU。

RTC表示让定时任务的触发时间从1970年1月1日0点开始算起,但不会唤醒CPU。

RTC_WAKEUP表示让定时任务的触发时间从1970年1月1日0点开始算起,但会唤醒CPU。

使用SystemClock.elapsedRealtime()方法可以获取到系统开机至今所经历时间的毫秒数,使用System.currentTimeMillis()方法可以获取到1970年1月1日0点至今所经历时间的毫秒数

 

第二个参数代表定时任务触发的时间,以毫秒为单位。

如果第一个参数使用的是ELAPSED_REALTIME或ELAPSED_REALTIME_WAKEUP,则这里传入开机至今的时间再加上延迟执行的时间。

如果第一个参数使用的是RTC或RTC_WAKEUP,则这里传入1970年1月1日0点至今的时间再加上延迟执行的时间。

 

第三个参数是一个PendingIntent,一般会调用getService()方法或者getBroadcast()方法来获取一个能够执行服务或广播的PendingIntent。这样当定时任务被触发的时候,服务的onStartCommand()方法或广播接收器的OnReceive()方法就可以得到执行。

 

实现一个长时间在后台定时运行的服务

 

public class LongRunningService extends Service {

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
    
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        new Thread(new Runnable(){

            @Override
            public void run() {
                
            }
            
        }).start();
        AlarmManager manager = (AlarmManager) getSystemService(ALARM_SERVICE);
        int anHour = 60 * 60 * 1000;
        long triggerAtTime = SystemClock.elapsedRealtime() + anHour;
        Intent i = new Intent(this, LongRunningService.class);
        PendingIntent pi = PendingIntent.getService(this, 0, i, 0);
        manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerAtTime, pi);
        return super.onStartCommand(intent, flags, startId);
    }

}

在onStartCommand()方法中开启了一个子线程,并在这里执行逻辑操作。因为逻辑操作需要耗时,如果放在主线程里执行可能会对定时任务的准确性造成轻微的影响

最后,只需要在你想启动定时服务的时候调用如下代码即可:

Intent intent = new Intent(context, LongRunningService.class);

context.startService(intent);

 

注意:从Android4.4系统开始,Alarm任务的触发时间将会变得不准确,有可能会延迟一段时间后任务才能得到执行。这是系统在耗电性能方面进行的优化。系统会自动检测目前有多少Alarm任务存在,然后将触发时间相近的几个任务放在一起执行,这就可以大幅度地减少CPU被唤醒的次数,从而有效延长电池的使用时间。

如果你要求Alarm任务的执行时间必须准确无误,使用AlarmManager的setExact()方法来替代set()方法,就基本上可以保证任务能够准时执行了。

安卓笔记20170118