在本应在指定时间触发警报的应用程序中,该警报的目的是通过Notification通知用户,因此我对获得不精确的结果感到绝望。警报正在响起,但未在指定时间响起。当警报设置和应该发出的时间之间的时间很长时,这是系统的。
为此,我使用了setExact(RTC_WAKEUP,time,intent)。经过多次尝试使其工作后,我终于看到并尝试了setAlarmClock函数,一切正常!

根据javadoc,setAlarmClocksetExact相同,只是它暗示RTC_WAKEUP。据我所知,至少存在另一个区别。有人知道吗?

最佳答案

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()设置的警报会唤醒。

09-27 14:19