【问题标题】:setRepeating() of AlarmManager repeats after 1 minute no matter what the time is set (5 seconds in this case, API 18+)无论设置什么时间,AlarmManager 的 setRepeating() 都会在 1 分钟后重复(本例中为 5 秒,API 18+)
【发布时间】:2016-10-13 17:58:58
【问题描述】:

我已将重复时间设置为 5 秒。第一个 toast 会在 5 秒后出现,但下一次会在 1 分钟后重复。
我也尝试了 setRepeating() 的代码,它仍然不起作用。
这是我的代码:

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();
}

【问题讨论】:

标签: android alarmmanager


【解决方案1】:

文档需要更新。截至我认为Android 5.1(API版本22)重复警报的最短时间为1分钟,并且将来的警报不能设置为小于5秒。

如果您需要在一分钟内完成工作,只需直接设置闹钟,然后从该闹钟的处理程序中设置下一个,等等。

如果您需要在 5 秒内完成工作,请将其发布到 Handler,而不是使用警报管理器?

【讨论】:

  • 根据经验测试,这似乎相当准确。我测试了许多运行 5.0、5.1 和 6.x 的设备。设置 15 秒的重复警报会在不同的设备上生成 15 秒到 10 分钟的重复警报。三星设备似乎更喜欢重复 5 分钟。这绝对是坏的,它绝对不符合文档(它特别指出,如果你的目标 API
【解决方案2】:

不要使用 setRepeating() 或 setInExactRepeating,它不会在 5 秒后重复。相反,尝试安排一次警报,然后在类似这样的 onReceive() 方法中再次重新安排它。这将在特定时间间隔(本例中为 5 秒)后重复

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】:

    试试这个代码:
    Calendar cal = Calendar.getInstance(); alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), 5000, pendingIntent);

    【讨论】:

    • 这段代码和我的一模一样,只是你已经拆分了触发时间的初始化部分。
    【解决方案4】:

    试试下面的代码:

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

    运行此代码后,警报将在 3 秒后首次触发,之后每 5 秒触发一次。

    还可以尝试使用WakefulBroadcastReceiver 而不是BroadcastReceiver,因为一段时间后手机似乎进入了打盹模式(如果您使用的是android M)。确保包含WAKE_LOCK 使用它的权限正确。

    此外,您必须记住,您的警报的第一次触发不会在请求的时间之前,但它可能不会在该时间之后的几乎整个间隔内发生。此外,虽然重复警报的整个周期将按要求进行,但任何两次连续触发警报之间的时间可能会有所不同。

    另外

    setInExactRepeating()不保证触发时间的准确性。您可以在 API 19 之前使用setRepeating(),但从 API 19 (KITKAT) 开始,警报传递是不准确的:操作系统将切换警报以最大程度地减少唤醒和电池使用。 您可以做的是,设置一个非重复警报,当警报触发时,您可以在BroadcastReceiver 中再次重置警报。有新的 API 来支持需要严格交付保证的应用程序;见setWindow(int, long, long, PendingIntent)setExact(int, long, PendingIntent)。 targetSdkVersion 早于 API 19 的应用程序将继续看到以前的行为,即所有警报都在请求时准确传递。

    参考

    setInexactRepeating() Official documentation

    StackOverflow answer

    【讨论】:

    • 这段代码和我的一模一样,除了“时间”中的额外 3 秒。我也尝试过使用 WakefulBroadcastReceiver,但仍然没有运气。我也看过文档。我怎样才能实现连续发射的精确重复时间? (在我的情况下是 5 秒)
    • 重复警报将不再为您提供准确的保证。如果您确实需要在任何给定点发出精确警报,则需要将一次性警报链接在一起:当每个警报触发时,将下一个安排为新的一次性精确警报。
    【解决方案5】:

    试试这个

        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);
    

    【讨论】:

    • "alarm.cancel(pintent);"取消匹配待处理意图的警报。因此,在这种情况下永远不会触发警报。
    【解决方案6】:

    试试这个

    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);
    
    }
    

    【讨论】:

    • 我已经用过 setRepeating() 了,没什么区别。它仍然会在 1 分钟而不是 5 秒后触发警报。
    【解决方案7】:

    我遇到了完全相同的问题。我花了几个小时调试这个,最后我发现如果重复时间设置为低于一分钟,它总是在一分钟的时间表上触发警报!?

    我遵循了这个例子: http://www.compiletimeerror.com/2015/02/how-to-make-alarm-repeat-in-android-code.html#.Vp5UrCorKM8

    它显示警报在 8 秒后触发,但在我的情况下它不会。

    我尝试将重复时间设置为几分钟,效果很好。我还喜欢从接收器发出警报可以提供更准确的重复时间(一个接收器用于启动警报管理器,它由自定义意图过滤器调用)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-12
      • 2012-07-19
      • 1970-01-01
      • 1970-01-01
      • 2013-04-19
      • 1970-01-01
      相关资源
      最近更新 更多