'setExact'和'setAlarmClock'

时间:2016-03-20 06:18:32

标签: java android alarm

在我的应用程序中,它应该在指定的时间触发警报,警报的目的是通过Notification通知用户,我对获得非精确结果感到绝望。警报振铃,但不是在指定的时间。当警报设置和应该关闭的时间之间的时间很长时,这是系统性的。 为此,我使用setExact(RTC_WAKEUP,time,intent)。经过多次尝试才能使它工作,我终于看到并尝试了setAlarmClock功能,一切都很顺利!!

根据javadoc,setAlarmClocksetExact相同,但它隐含RTC_WAKEUP。据我所知,至少存在另一个差异。有谁知道吗?

2 个答案:

答案 0 :(得分:7)

setExact()setAlarmClock()setImpl()的调用非常相似。如果您使用RTC_WAKEUP进行setExact()来电,则唯一的区别是AlarmClockInfo类型的最终参数。

在服务方面,呼叫在set()中收到。在该方法结束时,我们可以看到额外参数的区别:

@Override
public void set(int type, long triggerAtTime, long windowLength, long interval, int flags,
        PendingIntent operation, WorkSource workSource,
        AlarmManager.AlarmClockInfo alarmClock) {
    final int callingUid = Binder.getCallingUid();
    if (workSource != null) {
        getContext().enforcePermission(
                android.Manifest.permission.UPDATE_DEVICE_STATS,
                Binder.getCallingPid(), callingUid, "AlarmManager.set");
    }

    // No incoming callers can request either WAKE_FROM_IDLE or
    // ALLOW_WHILE_IDLE_UNRESTRICTED -- we will apply those later as appropriate.
    flags &= ~(AlarmManager.FLAG_WAKE_FROM_IDLE
            | AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED);

    // Only the system can use FLAG_IDLE_UNTIL -- this is used to tell the alarm
    // manager when to come out of idle mode, which is only for DeviceIdleController.
    if (callingUid != Process.SYSTEM_UID) {
        flags &= ~AlarmManager.FLAG_IDLE_UNTIL;
    }

    // If the caller is a core system component, and not calling to do work on behalf
    // of someone else, then always set ALLOW_WHILE_IDLE_UNRESTRICTED.  This means we
    // will allow these alarms to go off as normal even while idle, with no timing
    // restrictions.
    if (callingUid < Process.FIRST_APPLICATION_UID && workSource == null) {
        flags |= AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED;
    }

    // If this is an exact time alarm, then it can't be batched with other alarms.
    if (windowLength == AlarmManager.WINDOW_EXACT) {
        flags |= AlarmManager.FLAG_STANDALONE;
    }

    // If this alarm is for an alarm clock, then it must be standalone and we will
    // use it to wake early from idle if needed.
    if (alarmClock != null) {
        flags |= AlarmManager.FLAG_WAKE_FROM_IDLE | AlarmManager.FLAG_STANDALONE;
    }

    setImpl(type, triggerAtTime, windowLength, interval, operation,
            flags, workSource, alarmClock, callingUid);
}

如果存在非空alarmClock参数,则请求会在FLAG_WAKE_FROM_IDLE之上获取FLAG_STANDALONE标记,这两种情况都会得到。 FLAG_WAKE_FROM_IDLE的评论说:

  

警报标志:此警报即使在空闲时也会唤醒设备。例如,这是闹钟的警报。

如果你愿意,你可以dig into the usage of FLAG_WAKE_FROM_IDLE - 但就我所知,这就是区别。您的“正常”确切警报不会将设备从空闲状态唤醒,但使用setAlarmClock()设置的警报会启动。

答案 1 :(得分:3)

Android 6.0(API级别23)中引入的

Doze mode为上面列出的内容添加了进一步的限制:( TL; DR:打盹模式下只有setAlarmClock个触发器,adds a system icon

  

打盹限制

     

以下限制适用于您在Doze中的应用:[...]

     
      
  • 系统会忽略唤醒锁定。
  •   
  • 标准AlarmManager警报(包括setExact()setWindow())将推迟到下一个维护时段。      
        
    • 如果您需要设置在Doze中触发的闹钟,请使用setAndAllowWhileIdle()setExactAndAllowWhileIdle()
    •   
    • 使用setAlarmClock()设置的警报继续正常启动 - 系统在警报触发前不久退出Doze。   [...]
    •   
  •   

设备进入低功耗打盹状态,定期唤醒以执行其他警报等。