AlarmManager使用

AlarmManager使用

AlarmManager简介
  • AlarmManager接口
  • 常用接口
    Alarm问题分析
  • Batch队列里面的一个Batch
  • 非唤醒alarm延时统计
  • Top Alarm
  • Alarm统计
    反馈与建议
  • AlarmManager简介

    AlarmManager这个类提供对系统闹钟服务的访问接口。你可以为你的应用设定一个在未来某个时间唤醒的功能。当闹钟响起,实际上是系统发出了为这个闹钟注册的广播,会自动开启目标应用。注册的闹钟在设备睡眠的时候仍然会保留,可以选择性地设置是否唤醒设备,但是当设备关机和重启后,闹钟将会被清除。

    在alarm的receiver的onReceive()方法被执行的时候,AlarmManager持有一个CPU唤醒锁,这样就保证了设备在处理完广播之前不会sleep。一旦onReceive()方法返回,AlarmManager就会释放这个锁,表明一些情况下可能onReceive()方法一执行完设备就会sleep。如果你的alarmreceiver中调用了Context.startService(),那么很可能service还没起来设备就sleep了。为了阻止这种情况,你的BroadcastReceiver和Service需要实现不同的唤醒锁机制,来确保设备持续运行到service可用为止。

    注意:Alarm Manager主要是用来在特定时刻运行你的代码,即便是你的应用在那个特定时刻没有跑的情况。对于常规的计时操作(ticks, timeouts, etc),使用Handler处理更加方便和有效率。另:从API 19开始,alarm的机制都是非准确传递,操作系统将会转换闹钟,来最小化唤醒和电池使用。有一些新的API会支持严格准确的传递,见 setWindow(int, long, long, PendingIntent)和setExact(int, long, PendingIntent)。targetSdkVersion在API19之前应用仍将继续使用以前的行为,所有的闹钟在要求准确传递的情况下都会准确传递。

    AlarmManager接口


    1、 cancel(PendingIntent operation) Remove any alarms with a matching Intent.

    2、 changeAlarmType(String pkgName, boolean wakeup)

    3、 getNextAlarmClock()

    Gets information about the next alarm clock currently scheduled.

    4、 set(int type, long triggerAtMillis, PendingIntent operation)

    Schedule an alarm.

    5、 setAlarmClock(AlarmManager.AlarmClockInfo info, PendingIntent operation)

    Schedule an alarm that represents an alarm clock.

    6、 setExact(int type, long triggerAtMillis, PendingIntent operation)

    Schedule an alarm to be delivered precisely at the stated time.

    7、 setInexactRepeating(int type, long triggerAtMillis, long intervalMillis, PendingIntent operation)

    Schedule a repeating alarm that has inexact trigger time requirements; for example, an alarm that repeats every hour, but not necessarily at the top of every hour.

    8、 setRepeating(int type, long triggerAtMillis, long intervalMillis, PendingIntent operation)

    Schedule a repeating alarm.

    9、 setTime(long millis)

    Set the system wall clock time.

    10、 setTimeZone(String timeZone)

    Set the system default time zone.

    11、 setWindow(int type, long windowStartMillis, long windowLengthMillis, PendingIntent operation)

    Schedule an alarm to be delivered within a given window of time.

    常用接口

    public void cancel (PendingIntent operation)

    移除intent相匹配的alarm(只要action,data, type,class,categories相等,就会被取消)
    Remove any alarms with a matching Intent. Any alarm, of any type, whose Intent matches this one (as defined by filterEquals(Intent)), will be canceled.

    public void set(int type, long triggerAtMillis, PendingIntent operation)

    该方法用于设置一次性闹钟
    第一个参数int type 指定定时服务的类型,该参数接受如下值:
    ELAPSED_REALTIME在指定的延时过后,发送广播,但不唤醒设备(闹钟在睡眠状态下不可用)。如果在系统休眠时闹钟触发,它将不会被传递,直到下一次设备唤醒。
    ELAPSED_REALTIME_WAKEUP 在指定的延时过后,发送广播,并唤醒设备(即使关机也会执行operation所对应的组件)。延时是要把系统启动的时间SystemClock.elapsedRealtime()算进去的,具体用法看代码。
    RTC指定当系统调用System.currentTimeMillis()方法返回的值与triggerAtTime相等时启动operation所对应的设备(在指定的时刻,发送广播,但不唤醒设备)。如果在系统休眠时闹钟触发,它将不会被传递,直到下一次设备唤醒(闹钟在睡眠状态下不可用)。
    RTC_WAKEUP指定当系统调用System.currentTimeMillis()方法返回的值与triggerAtTime相等时启动operation所对应的设备(在指定的时刻,发送广播,并唤醒设备)。即使系统关机也会执行 operation所对应的组件。
    第二个参数triggerAtMillis表示触发闹钟的时间。
    第三个参数PendingIntent operation表示闹钟响应动作:
    PendingIntent operation:是闹钟的执行动作,比如发送一个广播、给出提示等等。PendingIntent是Intent的封装类。需要注意的是:
    启动服务:如果是通过启动服务来实现闹钟提示的话,PendingIntent对象的获取就应该采用Pending.getService(Context c,int i,Intent intent,int j)方法;
    启动广播:如果是通过广播来实现闹钟提示的话,PendingIntent对象的获取就应该采用PendingIntent.getBroadcast(Context c,inti,Intent intent,int j)方法;
    启动activity:如果是采用Activity的方式来实现闹钟提示的话,PendingIntent对象的获取就应该采用PendingIntent.getActivity(Context c,inti,Intent intent,int j)方法。
    如果这三种方法错用了的话,虽然不会报错,但是看不到闹钟提示效果。
    注意:AndroidL开始,设置的alarm的触发时间必须大于当前时间 5秒
    AlarmManagerService中是通过PendingItent来标示一个Alarm的
    AndroidL开始系统有了非唤醒Alarm在黑屏状况下会推迟触发,推迟的时间通过当前黑屏时间计算出来,但一但有唤醒Alarm,则随着触发
    MTK平台关闭了该功能,三星平台依然保留该功能

    public void setRepeating(int type,long startTime,long intervalTime,PendingIntent pi)

  • 设置一个周期性执行的定时服务。第一个参数表示闹钟类型,第二个参数表示闹钟首次执行时间,第三个参数表示闹钟两次执行的间隔时间,第三个参数表示闹钟响应动作。
  • 注意:改方法提供了设置周期闹钟的入口,闹钟执行时间严格按照startTime来处理,使用该方法需要的资源更多,不建议使用。

    public void setInexactRepeating(int type,long startTime,long intervalTime,PendingIntent pi)

    该方法也用于设置重复闹钟,与第二个方法相似,不过其两个闹钟执行的间隔时间不是固定的而已。它相对而言更省电(power-efficient)一些,因为系统可能会将几个差不多的闹钟合并为一个来执行,减少设备的唤醒次数。第三个参数intervalTime为闹钟间隔,内置的几个变量如下:
    INTERVAL_DAY设置闹钟,间隔一天
    INTERVAL_HALF_DAY 设置闹钟,间隔半天
    INTERVAL_FIFTEEN_MINUTES设置闹钟,间隔15分钟
    INTERVAL_HALF_HOUR 设置闹钟,间隔半个小时
    INTERVAL_HOUR设置闹钟,间隔一个小时
    AndroidL开始repeat的周期必须大于60秒

    Alarm问题分析


    1.dumpsys alarm

    查看设置的alarm

    Current Alarm Manager state:
    nowRTC=1452484905420=2016-01-11 12:01:45 nowELAPSED=+2d19h30m57s573ms
    Time since non-interactive: +8m29s723ms 从上一次灭屏开始计算的时间
    Max wakeup delay: +15m0s0ms 最大的唤醒延时
    Time since last dispatch: +1s746ms 距离上一个触发alarm的时间
    Next non-wakeup delivery time: -21m44s581ms 下一个非唤醒alarm触发时间
    Next non-wakeup alarm: +14s580ms = 2016-01-11 12:02:00 下一个非唤醒alarm触发时间
    Next wakeup: +1h2m30s289ms = 2016-01-11 13:04:15 下一次唤醒时间
    Num time change events: 1 时间改变的次数
    Pending alarm batches: 21 在队列中的alarm

    Batch队列里面的一个Batch

    Batch{18f03fc3 num=3 start=286152153 end=286152153}:
    RTC #2: Alarm{258ac040 type 1 when 00:00:00 start 23:59:59 end 00:00:00 com.meizu.flyme.launcher}
    tag=*alarm*:notify.launcher.date.change
    type=1 whenElapsed=+8h27m32s45ms when=2016-01-12 00:00:00
    start =00:00:00 whenElapsed=00:00:00 end=00:00:00 fixed=true aligned=false window=-1 repeatInterval=0 count=0
    operation=PendingIntent{34278b79: PendingIntentRecord{19eb70be com.meizu.flyme.launcher broadcastIntent}}
    RTC #1: Alarm{368d151f type 1 when 00:00:00 start 00:00:00 end 00:00:00 com.meizu.flyme.input}
    tag=*alarm*:notify.ime.date.change
    type=1 whenElapsed=+8h27m32s45ms when=2016-01-12 00:00:00
    start =23:59:59 whenElapsed=00:00:00 end=00:00:00 fixed=true aligned=false window=-1 repeatInterval=0 count=0
    operation=PendingIntent{2b7ba06c: PendingIntentRecord{2e0c6635 com.meizu.flyme.input broadcastIntent}}
    RTC #0: Alarm{3070ddc8 type 1 when 00:00:00 start 00:00:00 end 00:00:00 com.android.calendar}
    tag=*alarm*:com.android.calendar.APPWIDGET_SCHEDULED_UPDATE
    type=1 whenElapsed=+8h27m32s45ms when=2016-01-12 00:00:00
    start =00:00:00 whenElapsed=00:00:00 end=00:00:00 fixed=true aligned=false window=0 repeatInterval=0 count=0
    operation=PendingIntent{14518e61: PendingIntentRecord{38b85758 com.android.calendar broadcastIntent}}

    非唤醒alarm延时统计

    Past-due non-wakeup alarms: (none)
    Number of delayed alarms: 482, total delay time: +1d22h49m26s7ms
    Max delay time: +1h29m59s657ms, max non-interactive time: +2d16h18m22s465ms

    Top Alarm

    Top Alarms:
    +59s476ms running, 0 wakeups, 316 alarms: 1000:android
    *alarm*:android.intent.action.TIME_TICK
    +42s217ms running, 0 wakeups, 143 alarms: 1000:android
    *alarm*:com.android.server.action.NETWORK_STATS_POLL
    +25s765ms running, 0 wakeups, 48 alarms: 1000:com.meizu.safe
    *alarm*:pm.nonwakeup.powergauge.stats
    +20s491ms running, 0 wakeups, 23 alarms: 1000:android
    *alarm*:android.appwidget.action.APPWIDGET_UPDATE
    +17s353ms running, 0 wakeups, 11 alarms: 1000:android
    *alarm*:android.content.jobscheduler.JOB_DELAY_EXPIRED
    +16s417ms running, 5 wakeups, 5 alarms: u0a3:com.android.providers.calendar
    *walarm*:com.android.providers.calendar.intent.CalendarProvider2
    +10s623ms running, 15 wakeups, 15 alarms: u0a29:com.android.systemui
    *walarm*:com.android.internal.policy.impl.PhoneWindowManager.DELAYED_KEYGUARD
    +6s406ms running, 0 wakeups, 3 alarms: 1000:android
    *alarm*:android.intent.action.DATE_CHANGED
    +5s186ms running, 0 wakeups, 8 alarms: 1000:com.meizu.experiencedatasync
    *alarm*:com.meizu.usagestats.check_upload
    +3s695ms running, 0 wakeups, 7 alarms: 1000:android
    *alarm*:android.content.jobscheduler.JOB_DEADLINE_EXPIRED

    Alarm统计




    Alarm Stats:
    1000:android +1m53s845ms running, 14 wakeups:
    +59s476ms 0 wakes 316 alarms: alarm:android.intent.action.TIME_TICK
    +42s217ms 0 wakes 143 alarms: alarm:com.android.server.action.NETWORK_STATS_POLL
    +20s491ms 0 wakes 23 alarms: alarm:android.appwidget.action.APPWIDGET_UPDATE
    ……………………….
    alarm:com.android.server.action.UPDATE_APPROXIMATELY_TWILIGHT_STATE
    +132ms 8 wakes 8 alarms:
    walarm:com.android.server.task.controllers.BatteryController.ACTION_CHARGING_STABLE
    +130ms 3 wakes 3 alarms:
    1000:com.meizu.safe +26s53ms running, 6 wakeups:
    +25s765ms 0 wakes 48 alarms: alarm:pm.nonwakeup.powergauge.stats
    +131ms 3 wakes 3 alarms: walarm:tmsdk.common.actionreport
    …………………………
    1000:com.meizu.experiencedatasync +7s448ms running, 0 wakeups:
    +5s186ms 0 wakes 8 alarms: alarm:com.meizu.usagestats.check_upload
    +2s262ms 0 wakes 2 alarms: alarm:com.meizu.experiencedatasync.check_upload
    u0a3:com.android.providers.calendar +18s156ms running, 8 wakeups:
    +16s417ms 5 wakes 5 alarms:
    walarm:com.android.providers.calendar.intent.CalendarProvider2
    +1s739ms 3 wakes 3 alarms:
    walarm:com.android.providers.calendar.SCHEDULE_ALARM
    u0a5:com.meizu.customizecenter +1s282ms running, 0 wakeups:
    +1s282ms 0 wakes 5 alarms:
    alarm:com.meizu.customizecenterservice.download.CHECK_UPDATE
    u0a13:com.meizu.flyme.launcher +1s522ms running, 0 wakeups:
    +1s522ms 0 wakes 3 alarms:
    alarm:notify.launcher.date.change
    u0a22:com.meizu.flyme.input +1s599ms running, 0 wakeups:
    +1s599ms 0 wakes 3 alarms:
    alarm:notify.ime.date.change
    u0a29:com.android.systemui +10s623ms running, 15 wakeups:
    +10s623ms 15 wakes 15 alarms:
    walarm:com.android.internal.policy.impl.PhoneWindowManager.DELAYED_KEYGUARD

    反馈与建议

    如以上描述有问题的地方或者有其他建议,请发邮件给我,如果大家有更多的经验总结,还请不吝赐教,我将持续完善此文档,谢谢!。

    你可能感兴趣的:(Alarm,Android)