报菜名

​ AlarmManager可用于计划未来的单次或重复的操作,甚至在应用程序没有运行时也可以执行任务,它通过PendingIntent触发执行各种**系统组件,**如BroadcastReceiver,Activity或Service等。

​ 或者说AlarmManager比较适用于应用程序没有运行但仍然需要执行某些操作的场景。如果程序运行时需要执行简单的定时操作,使用Handler的postAtTime()和postDelay()就可以了。

在设备重启后,提醒自动失效,需要手动计划之前注册的提醒

注意事项

唤醒类型

ELAPSED_REALTIMEELAPSED_REALTIME_WAKEUPRTCRTC_WAKEUP
根据设备上次启动以来的时间值(毫秒)触发提醒根据经过的时间触发提醒,如果设备处于休眠状态,将被激活根据UTC时间触发警告根据UTC时间触发警告,如果设备处于休眠状态,将被激活

注意,如果使用ELAPSED_REALTIME_WAKEUPRTC_WAKEUP这种唤醒类型的提醒,系统虽然会被唤醒但是不会保持唤醒状态,在执行唤醒事件的后台工作时,需要通过PowerManager获得WakeLock,否则系统会重新将设备转入休眠状态,你要本要执行的操作也会被停止。

###PendingIntent

PendingIntent有很多构造方法,但是必须要保证它能正确的指向要触发的应用程序组件。

pendingintent.png

上菜

AlarmReceiver

public class AlarmReceiver extends BroadcastReceiver {
    private IntentFilter mIntentFilter;
    public static final String ACTION_ALARM = "ACTION_ALARM";

    public AlarmReceiver() {
        mIntentFilter = new IntentFilter();
        mIntentFilter.addAction(ACTION_ALARM);
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        if (mIntentFilter.matchAction(intent.getAction())) {
            Calendar now = Calendar.getInstance();
            Toast.makeText(context,
                    "Msg:" + SimpleDateFormat.getTimeInstance().format(now.getTime()),
                    Toast.LENGTH_SHORT).show();
        }
    }
}

注意注册:

 <receiver android:name=".AlarmReceiver"/>

AlarmActivity

public class AlarmActivity extends AppCompatActivity {

    private AlarmManager mAlarmManager;
    private PendingIntent mPendingIntent;
    private Intent mIntent;
    private long mInterval = 5000;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_alarm);
        mAlarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
        mIntent = new Intent(this,AlarmReceiver.class);
        mIntent.setAction(AlarmReceiver.ACTION_ALARM);
        mPendingIntent = PendingIntent.getBroadcast(this, 0, mIntent, 0);
    }

    public void start(View view) {
        mAlarmManager.setRepeating(
                AlarmManager.ELAPSED_REALTIME,
                SystemClock.elapsedRealtime() + mInterval,
                mInterval,
                mPendingIntent);
    }

    public void cancle(View view) {
        mAlarmManager.cancel(mPendingIntent);
    }
}

示例2

每天上午9点执行任务

public void start2(View view) {
        long oneDay=24*3600*100;
        long firstTime;
        //创建一个日历,并设置提醒的时间为09:00
        Calendar startTime = Calendar.getInstance();
        startTime.set(Calendar.HOUR_OF_DAY,9);
        startTime.set(Calendar.MINUTE,0);
        startTime.set(Calendar.SECOND,0);

        Calendar now=Calendar.getInstance();
        if (now.before(startTime)){
            //现在还没到上午9点,从今天算起
            firstTime=startTime.getTimeInMillis();
        }else{
            //从明天上午9点算起
            startTime.add(Calendar.DATE,1);
            firstTime=startTime.getTimeInMillis();
        }
        //设置提醒
        mAlarmManager.setRepeating(
                AlarmManager.RTC_WAKEUP,
                firstTime,
                oneDay,
                mPendingIntent);
    }

最后

​ 十九岁那年的分水岭,Android4.4(19)开始所有的提醒都是不准确的,这意味着讲通过一个小窗口触发它们,连同这个新行为还一起添加了API方法setExat(),通过这个方法我们可以声明下面的提醒不能放入不准确的窗口。