AlarmManager的setInexactRepeating在指定的触发时间之前触发。

huangapple go评论72阅读模式
英文:

AlarmManager setInexactRepeating fires before specified trigger time

问题

我知道 setInexactRepeating 并不是精确的,但它也表示在请求的时间之前不会触发,这在我的情况下似乎是发生了。我将闹钟设置为每隔 10001 毫秒触发一次,然后使用普通的可运行计时器在 10000 毫秒后取消它(取消闹钟似乎工作正常),然后在该可运行计时器中再次设置闹钟,使其在每隔 10001 毫秒后触发,但有时它会在新的闹钟中设置的时间之前提前触发。闹钟甚至不应该触发,因为我使用可运行计时器来取消它,并且手机没有休眠,所以计时器一直在运行。

我的代码:

// MainService.java:
public static void setAlarm(Context context) {
    Intent intent = new Intent(context, AlarmBroadcastReceiver.class);
    PendingIntent pIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
    AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
    if (alarmManager != null) {
        alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 10001, 10001, pIntent);
        MainActivity.showToast(appContext, "set alarm: " + (System.currentTimeMillis() + 10001));
    }
}

public static void cancelAlarm(Context context) {
    Intent intent = new Intent(context, AlarmBroadcastReceiver.class);
    PendingIntent pIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_NO_CREATE);
    if (pIntent != null) {
        AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        if (alarmManager != null) {
            alarmManager.cancel(pIntent);
            MainActivity.showToast(appContext, "cancel alarm");
        }
    }
}

public static Runnable timerInterval = new Runnable() {
    public void run() {
        cancelAlarm(appContext);
        handler.postDelayed(timerInterval, 10000);
        setAlarm(appContext);
    }
};

// AlarmBroadcastReceiver.java:
public class AlarmBroadcastReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        MainActivity.showToast(context, "alarm");
        if (MainService.service) {
            MainService.handler.removeCallbacks(MainService.timerInterval);
            MainService.handler.postDelayed(MainService.timerInterval, 10000);
        }
    }
}

这是预期的行为吗?还是我做错了什么?

英文:

I know that setInexactRepeating is not exact but it also says that it will not fire before the requested time, which seems to happen in my case. I set the alarm to fire after every 10001 milliseconds and cancel it after 10000 milliseconds using a regular runnable timer (cancelling the alarm seems to work fine) and set the alarm again to fire after every 10001 milliseconds in that runnable timer but sometimes it will fire earlier before the new requested time set in the new alarm. The alarm should not even fire at all since I use the runnable timer to cancel it and the phone is not sleeping, so the timer is running all the time.

My code:

//MainService.java:
public static void setAlarm(Context context) {
Intent intent = new Intent(context, AlarmBroadcastReceiver.class);
PendingIntent pIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
if (alarmManager != null) {
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 10001, 10001, pIntent);
MainActivity.showToast(appContext, "set alarm: " + (System.currentTimeMillis() + 10001));
}
}
public static void cancelAlarm(Context context) {
Intent intent = new Intent(context, AlarmBroadcastReceiver.class);
PendingIntent pIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_NO_CREATE);
if (pIntent != null) {
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
if (alarmManager != null) {
alarmManager.cancel(pIntent);
MainActivity.showToast(appContext, "cancel alarm");
}
}
}
public static Runnable timerInterval = new Runnable() {
public void run() {
cancelAlarm(appContext);
handler.postDelayed(timerInterval, 10000);
setAlarm(appContext);
}
};
//AlarmBroadcastReceiver.java:
public class AlarmBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
MainActivity.showToast(context, "alarm");
if (MainService.service) {
MainService.handler.removeCallbacks(MainService.timerInterval);
MainService.handler.postDelayed(MainService.timerInterval, 10000);
}
}
}

Is this the intended behavior? Or am I doing something wrong?

答案1

得分: 0

以下是翻译好的部分:

这是我能想出的唯一解决方案。我认为这是因为alarmManager.cancel(pIntent)存在一些延迟,有时候它无法及时取消闹钟,闹钟事件将会触发(尽管应该被取消),所以当发生这种情况时,我基本上会忽略它,但这似乎有点像是一种不太正规的方法。如果有人知道一种合适的立即取消闹钟的方法,请告诉我们!

//MainService.java:
public static void setAlarm(Context context) {
    Intent intent = new Intent(context, AlarmBroadcastReceiver.class);
    PendingIntent pIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
    AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
    if (alarmManager != null) {
        alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 10001, 10001, pIntent);
        MainActivity.showToast(appContext, "set alarm: " + (System.currentTimeMillis() + 10001));
    }
}

public static void cancelAlarm(Context context) {
    Intent intent = new Intent(context, AlarmBroadcastReceiver.class);
    PendingIntent pIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_NO_CREATE);
    if (pIntent != null) {
        AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        if (alarmManager != null) {
            alarmManager.cancel(pIntent);
            MainActivity.showToast(appContext, "cancel alarm");
        }
    }
}

public static long timerIntervalTime;
public static Runnable timerInterval = new Runnable() {
    public void run() {
        timerIntervalTime = System.currentTimeMillis();

        cancelAlarm(appContext);
        handler.postDelayed(timerInterval, 10000);
        setAlarm(appContext);
    }
};

//AlarmBroadcastReceiver.java:
public class AlarmBroadcastReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        if (MainService.service) {
            if ((System.currentTimeMillis() - MainService.timerIntervalTime) >= 10001) { //this alarm was canceled but for some reason still fired, possibly because of some delay with canceling
                MainActivity.showToast(context, "alarm");

                MainService.handler.removeCallbacks(MainService.timerInterval);
                MainService.handler.postDelayed(MainService.timerInterval, 10000);
            }
        }
    }
}
英文:

This is the only solution I could come up with. I think it is because there is some delay with alarmManager.cancel(pIntent), sometimes it does not cancel it on time and the alarm event will fire (even though it is supposed to be canceled), so I'm basically ignoring it when that happens, but seems a bit like a hack to do it this way. If someone knows a proper way to instantly cancel the alarm, please let us know!

//MainService.java:
public static void setAlarm(Context context) {
Intent intent = new Intent(context, AlarmBroadcastReceiver.class);
PendingIntent pIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
if (alarmManager != null) {
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 10001, 10001, pIntent);
MainActivity.showToast(appContext, "set alarm: " + (System.currentTimeMillis() + 10001));
}
}
public static void cancelAlarm(Context context) {
Intent intent = new Intent(context, AlarmBroadcastReceiver.class);
PendingIntent pIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_NO_CREATE);
if (pIntent != null) {
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
if (alarmManager != null) {
alarmManager.cancel(pIntent);
MainActivity.showToast(appContext, "cancel alarm");
}
}
}
public static long timerIntervalTime;
public static Runnable timerInterval = new Runnable() {
public void run() {
timerIntervalTime = System.currentTimeMillis();
cancelAlarm(appContext);
handler.postDelayed(timerInterval, 10000);
setAlarm(appContext);
}
};
//AlarmBroadcastReceiver.java:
public class AlarmBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (MainService.service) {
if ((System.currentTimeMillis() - MainService.timerIntervalTime) >= 10001) { //this alarm was canceled but for some reason still fired, possibly because of some delay with canceling
MainActivity.showToast(context, "alarm");
MainService.handler.removeCallbacks(MainService.timerInterval);
MainService.handler.postDelayed(MainService.timerInterval, 10000);
}
}
}
}

huangapple
  • 本文由 发表于 2020年9月19日 23:01:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/63970146.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定