setRepeating() of AlarmManager repeats after 1 min

2019-03-24 06:04发布

问题:

I have set the repeat time to 5 seconds. The first toast appears after 5 seconds, but all the next once repeat after 1 minute.
I tried the code with setRepeating() as well, it still doesn't work.
here is my code:

public void constructJob(){

    Intent alertIntent = new Intent(this, AlarmManagerService.class);
    PendingIntent pendingIntent = PendingIntent.getBroadcast(
            this, 0,
            alertIntent,
            PendingIntent.FLAG_UPDATE_CURRENT);

    AlarmManager alarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
    alarmManager.setInexactRepeating(
            AlarmManager.RTC_WAKEUP,
            GregorianCalendar.getInstance().getTimeInMillis(),
            repeatTime(),
            pendingIntent
    );

}

public long repeatTime(){
    return 5000;
}

AlarmManagerService.java

public class AlarmManagerService extends BroadcastReceiver {
      @Override
      public void onReceive(Context context, Intent intent) {
             Toast.makeText(context, "5 seconds have passed",
                            Toast.LENGTH_SHORT).show();
}

回答1:

The documentation needs to be updated. As of I think Android 5.1 (API version 22) there is a minimum period of 1 minute for repeating alarms, and alarms cannot be set less than 5 seconds in the future.

If you need to do work within one minute, just set the alarm directly, then set the next one from that alarm's handler, etc.

If you need to do work within 5 seconds, post it to a Handler instead of using the alarm manager?



回答2:

Don't use setRepeating() or setInExactRepeating, it won't repeat after exactly 5 seconds. Instead, try scheduling the alarm once, then reschedule it again in the onReceive() method something like this. This will repeat after a particular time interval (5 seconds in this case)

MainActivity.java

public class MainActivity extends AppCompatActivity {

Button btnStartAlarm, btnStopAlarm;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    btnStartAlarm = (Button) findViewById(R.id.btnStartAlarm);
    btnStopAlarm = (Button) findViewById(R.id.btnStopAlarm);

    Intent intent = new Intent(MainActivity.this, AlarmReceiver.class);
    final PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 100, intent, 0);

    final AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);

    btnStartAlarm.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 5000, pendingIntent);
        }
    });

    btnStopAlarm.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            alarmManager.cancel(pendingIntent);
        }
    });
}
 }

AlarmReceiver.java

public class AlarmReceiver extends BroadcastReceiver {
public AlarmReceiver() {
}

@Override
public void onReceive(Context context, Intent intent) {

    Log.d("Javed", "onReceive called");
    Toast.makeText(context, "onReceive called", Toast.LENGTH_LONG).show();

    Intent intent1 = new Intent(context, AlarmReceiver.class);
    final PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 100, intent1, 0);
    final AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
    alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 5000, pendingIntent);
}
  }


回答3:

Try this code:
Calendar cal = Calendar.getInstance(); alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), 5000, pendingIntent);



回答4:

Try this

    Calendar cur_cal = new GregorianCalendar();

    PendingIntent pintent = PendingIntent.getService(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
    AlarmManager alarm = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
    alarm.cancel(pintent);
    alarm.setRepeating(AlarmManager.RTC, cur_cal.getTimeInMillis(), interval, pintent);


回答5:

Try following code:

Long time = new GregorianCalendar().getTimeInMillis() +  3000;
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP,time,5000, pendingIntent);

Once you run this code the alarm will first trigger after 3 sec and every 5 sec there after.

Also try using a WakefulBroadcastReceiver instead of BroadcastReceiver as it looks like the phone is going in doze mode after some time(If you are on android M).Make sure you include the WAKE_LOCK permission to use it correctly.

Additionally you must keep in mind,your alarm's first trigger will not be before the requested time, but it might not occur for almost a full interval after that time. In addition, while the overall period of the repeating alarm will be as requested, the time between any two successive firings of the alarm may vary.

Additionally

setInExactRepeating() does not guarantee accuracy of the triggering time. You can use setRepeating() before API 19 but beginning with API 19 (KITKAT) alarm delivery is inexact: the OS will shift alarms in order to minimize wakeups and battery use. What you can do is, set a non-repeating alarm and when the alarm triggers you can reset the alarm again in your BroadcastReceiver There are new APIs to support applications which need strict delivery guarantees; see setWindow(int, long, long, PendingIntent) and setExact(int, long, PendingIntent). Applications whose targetSdkVersion is earlier than API 19 will continue to see the previous behavior in which all alarms are delivered exactly when requested.

Reference

setInexactRepeating() Official documentation

StackOverflow answer



回答6:

Try This

public void constructJob(){
Intent alertIntent = new Intent(this, AlarmManagerService.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(
        this, 0,
        alertIntent,
        PendingIntent.FLAG_UPDATE_CURRENT);

AlarmManager alarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
alarmManager.setRepeating(
        AlarmManager.RTC_WAKEUP,
        GregorianCalendar.getInstance().getTimeInMillis(),
        1000*5,
        pendingIntent);

}


回答7:

I had exactly the same problem. I've spent a few hours debugging this, and finally I found out that if the repeating time is set to lower than one minute it always fires the alarm on one minute schedule !?

I followed this example: http://www.compiletimeerror.com/2015/02/how-to-make-alarm-repeat-in-android-code.html#.Vp5UrCorKM8

and it shows the alarm firing on 8 seconds, but in my case it wouldn't.

Than I tried with setting repeating time to few minutes and it worked fine. I also fond out that firing alarm from receiver gives more accurate repeat times (one receiver is for starting alarm manager and it is called by custom intent filter)