IntentService 的 PendingIntent 不起作用

PendingIntent with IntentService not working

以下代码非常适合 Activity:

Intent intent = new Intent(context, MyActivity.class);
PendingIntent operation = PendingIntent.getActivity(context, 
                              0, 
                              intent, 
                              PendingIntent.FLAG_UPDATE_CURRENT);
alarmmanager.setExact(AlarmManager.RTC_WAKEUP, 
                              startTime.getTimeInMillis(),
                              operation);

但是,当我对IntentService做同样的事情时,只有当startTime和我设置闹钟的时间在同一天时才有效。例如如果我今天设置的闹钟是下午 5 点,它会被执行,但是当我今天的闹钟设置为明天下午 5 点时,它不会被执行。如果这是 Activity 那么它适用于这两种情况。

Intent intent = new Intent(context, MyService.class);
PendingIntent operation = PendingIntent.getService(context, 
                              0, 
                              intent, 
                              PendingIntent.FLAG_UPDATE_CURRENT);
alarmmanager.setExact(AlarmManager.RTC_WAKEUP, 
                              startTime.getTimeInMillis(),
                              operation);

如何解决这个问题?

我要实现的目标是每天在准确的时间执行IntentService

添加用这一行替换你的行:

alarmmanager.setRepeating(AlarmManager.RTC_WAKEUP, 
                          startTime.getTimeInMillis(),
                          operation);

它将按照您在警报管理器中设置的特定时间间隔重复

这里有一个详细的答案查看底部的 link 以了解更多详细信息。 希望这会有所帮助。您的问题也可能与 android 版本有关,因此请查看 link 了解更多详情

app 获取 AlarmManager 的实例并使用 PendingIntent 设置警报。更多关于使用和设置警报的内容将在下一节中介绍。 AlarmManager 是支持 AlarmManagerService 的应用端接口。它抽象了 Binder 接口的细节,用于与托管 AlarmManagerService 的系统进程(system_server)进行通信。这两个组件管理应用程序设置的警报,并将正确发送 PendingIntent。此 manager/service 架构在整个 Android 框架中使用,用于安全和隔离目的。 system_server进程是普通应用所没有的运行权限。如果您不熟悉 Android 的权限使用,请参阅本文以获取有关应用程序进程和用户 ID 的更多详细信息。这些额外的权限允许 system_server 访问底层内核警报驱动程序。警报驱动程序管理设置警报以唤醒设备,而不管 SoC 的睡眠状态如何。

当警报被触发时,设备被唤醒(如果处于睡眠状态)并且 AlarmManagerService 会收到警报到期的通知。然后它将相应地发送 PendingIntent。这将导致 MyApp 中的适当组件被激活。如果 MyApp 还没有启动或者它的进程没有被缓存,它将会被启动以便组件可以被激活。

基本用法为

public class MyActivity extends Activity {
...
private AlarmManager  mAlarmMgr;
...
public void onCreate(Bundle savedInstance) {
    ...
    mAlarmMgr = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
    ...
}
...


}

让我们使用组件名称.

为我们的 MyActivity 创建一个 PendingIntent
Intent alarmIntent = new Intent(context, MyActivity.class);
PendingIntent pend = PendingIntent.getActivity(context,
                              0,
                              alarmIntent,
                              PendingIntent.FLAG_UPDATE_CURRENT);

现在我们有了 PendingIntent 和 AlarmManager,我们可以设置警报,以便在警报过期时触发 Activity。为此,我们需要弄清楚我们希望闹钟何时响起,以及它是应该唤醒设备还是仅在设备下次唤醒时发送。请记住,我们有两种不同的方法来指定闹钟的时间:经过时间或日历 (RTC) 时间。所以我们的选项是 ELAPSED_REALTIME、ELAPSED_REALTIME_WAKEUP、RTC 或 RTC_WAKEUP。 _WAKEUP 变体是我们的“攻击性”警报,我们希望设备从低电量中恢复过来以回调我们的应用程序。对于我们的示例应用程序,让我们在自定义 BroadcastReceiver 中进行设置,并让它在设备启动

后大约 30 秒触发我们的 Activity
public class MyBootReceiver extends BroadcastReceiver {
public void onReceive(Context, context, Intent intent) {
    ...
    AlarmManager alarmMgr =
        (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
    long wakeTime = SystemClock.elapsedRealtime() + 30000;
    alarmMgr.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, wakeTime, pend);
}
}

现在,当我们的设备启动并发送 BOOT_COMPLETED 广播时,我们的应用程序进程将启动,我们的接收器将设置警报以触发我们的 Activity 在大约 30 秒后启动。请注意,在 Android 3.1 或更高版本的设备上,您必须先在 BOOT_COMPLETED.

之前手动启动您的应用程序

感谢作者BLOG

如果您想使用 SetExact 设置重复警报,您必须同时停止所有其他未决意图,请检查此 link 这里有许多如何操作的示例!再次归功于这位作家

用此代码替换 AlarmManager:

alarmManager.setRepeating(AlarmManager.RTC, 
                          timeMills, 
                          AlarmManager.INTERVAL_DAY, 
                          pendingIntent);

对我有用。

The goal here I am trying to achieve is to execute IntentService every day at the exact time.

Google 使这个从一个版本到另一个版本变得越来越难。参见 Android AlarmManager setExact() is not exact。可能有两种方法可以解决您的问题:

  1. 你启动一个 activity,它启动服务(因为启动一个 Activity 似乎对你有用)
  2. 您使用 setExactAnd... or setAlarmClock. setAlarmClock also triggers in the new "doze" mode, see .

另一种方法是重新考虑为什么以及您是否真的需要它……或者 JobScheduler 是否不能更轻松地满足您的目的。