【问题标题】:Android Service won't run from AlarmManagerAndroid 服务不会从 AlarmManager 运行
【发布时间】:2013-05-01 05:46:11
【问题描述】:

我在从警报管理器运行服务时遇到问题。

我正在构建一个应用程序,在他的 Facebook 朋友的命名日通知所有者。这一切都很好,但通知不会出现。

我已经设置了一个 AlarmTask,它创建了 PendingIntent 并设置了 AlarmManager,如下所示:

public void run() {


    // Request to start are service when the alarm date is upon us

    Intent intent = new Intent(context, NotifyService.class);
    intent.putExtra(NotifyService.INTENT_NOTIFY, true);
    intent.putExtra("notifyID", ID);
    PendingIntent pendingIntent = PendingIntent.getService(context, ID, intent, 0);

    // Sets an alarm - note this alarm will be lost if the phone is turned off and on again
    am.set(AlarmManager.RTC_WAKEUP, date.getTimeInMillis(), pendingIntent);
}

每个命名日的 ID 都是特定的。

现在在我的 NotifyService 中,我已经设置了这些:

 @Override
public void onCreate() {
    super.onCreate();
    System.out.println("NOTIFICATION SERVICE onCreate()");
    mNM = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    super.onStartCommand(intent, flags, startId);
    System.out.println("INTENT RECIEVED: " + intent + " " + flags + " " + startId);

    // If this service was started by out AlarmTask intent then we want to show our notification
    if(intent.getBooleanExtra(INTENT_NOTIFY, false)){
        int ID = intent.getIntExtra("notifyID", -1);
        showNotification(ID);
    }
    // We don't care if this service is stopped as we have already delivered our notification
    return START_STICKY;
}

当我启动应用程序时,这两种方法都会执行一次,但是当通知出现时,什么都没有发生。

有没有办法测试AlarmManager 是否真的执行了PendingIntent? 我应该使用 IntentService 吗?为什么/如何?

非常感谢。

我尝试将其更改为 BroadcastReciever,如下所示:

public class NotificationBroadcastReciever extends BroadcastReceiver{

@Override
public void onReceive(Context context, Intent intent) {
    System.out.println("BROADCAST RECIEVED");

}

}

AlarmTask 位改成这样:

Intent intent = new Intent("NotificationBroadcast");
    intent.putExtra(NotifyService.INTENT_NOTIFY, true);
    intent.putExtra("notifyID", ID);
    PendingIntent pendingIntent = PendingIntent.getBroadcast(context.getApplicationContext(), ID, intent, 0);
     System.out.println("date for notification: " + date.get(Calendar.DAY_OF_MONTH) + "." + date.get(Calendar.MONTH) + "." + date.get(Calendar.YEAR));
     System.out.println("epoch time in milils: " + date.getTimeInMillis());
    // Sets an alarm - note this alarm will be lost if the phone is turned off and on again
    am.set(AlarmManager.RTC_WAKEUP, date.getTimeInMillis(), pendingIntent);

相关的清单部分如下所示:

  <receiver 
        android:name="cz.cvut.kubispe2.jmeniny.NotificationBroadcastReciever" 
        android:exported="false">
        <intent-filter>
            <action android:name="NotificationBroadcast" />
        </intent-filter>
    </receiver>

我检查了要设置的日期是否等于纪元时间,但仍然没有调用 onRecieve 方法。

【问题讨论】:

  • 您想在 am.set() 中添加一些延迟吗? date.getTimeInMillis() + DELAY_IN_MILLIS
  • 我正在尝试在指定日期开始通知(这里的日期是一个包含通知信息的日历实例),所以我认为没有必要延迟
  • 根据您的描述,服务在应用启动时启动,这似乎是现在或过去的时间,而不是未来的时间。否则为什么应用程序启动时服务会启动?添加日志消息,你的代码看起来没问题。
  • 这也许是可能的。有什么办法可以重新启动服务吗?我希望全年收到更多通知,而不仅仅是一个。
  • 当然。服务完成后,可以在一段时间后通过警报管理器安排新的 pendingIntent,然后自行关闭。

标签: android service alarmmanager


【解决方案1】:

当我启动应用程序时,这两种方法都会执行一次,但是当通知出现时,什么都没有发生。

_WAKEUP 警报只有在路由到 BroadcastReceiver 而不是 Service 时才能保证唤醒设备。只要您所做的工作非常短(1-2 毫秒),您就可以在onReceive()BroadcastReceiver 中安全地完成这项工作。您目前在Service 中所做的工作将符合条件。

除此之外,使用adb shell dumpsys alarm 确认您的闹钟已安排在您认为的时间。

我应该使用 IntentService 吗?

这肯定是比普通的Service 更好的选择,因为你在当前的实现中会泄露它。但是,_WAKEUP 的限制仍然存在,这就是为什么I wrote WakefulIntentService 有助于弥合差距。不过,在您目前所做的工作有限的情况下,只需使用 BroadcastReceiver 就足够了。

【讨论】:

  • 好吧,我不太确定如何阅读 dumpsys 日志。这是日志中的示例记录,您能帮我理解它的含义吗? RTC_WAKEUP #35: Alarm{44e31838 type 0 cz.cvut.kubispe2.jmeniny} type=0 when=1369227635942 repeatInterval=0 count=0 operation=PendingIntent{44ea5ac8: PendingIntentRecord{44f34048 cz.cvut.kubispe2.jmeniny broadcastIntent}}跨度>
  • @PetrKubišta:您可能希望在更新的设备或模拟器上进行测试。您看到的 when 可能是毫秒以来的 Unix 纪元。新环境的格式应该更像when=+11h1m38s567ms,显示小时/分钟/秒/毫秒,直到事件发生。
  • 我尝试按照您的建议将其更改为广播接收器,但功能仍然没有变化。我将代码更新为问题。还有什么建议吗?
  • 另外,我确实在我为测试设置的 dumpsys 中找到了警报,它被设置为正确的时间,并且意图是广播意图,我认为应该如此。
  • @PetrKubišta:我会从BroadcastReceiver 中删除&lt;intent-filter&gt;,删除android:exported="false"(删除&lt;intent-filter&gt; 后不需要),并使用显式Intent(@ 987654341@) 为PendingIntent。下面是一个示例应用程序来演示这一点,尽管它使用 WakefulIntentService 而不仅仅是 BroadcastReceivergithub.com/commonsguy/cw-omnibus/tree/master/AlarmManager/…
【解决方案2】:

尝试使用应用程序上下文。

PendingIntent pendingIntent = PendingIntent.getService(context.getApplicationContext(), ID, intent, 0);

并使用 android logs。然后你会看到它是否在你的控制台中运行

【讨论】:

  • 我尝试了应用程序上下文,但它仍然无法正常工作。此外,我可以在我的 Eclipse LogCat 中看到 System.out。我知道它不是很安卓,但我没有太多时间,改变它需要一些时间。不过还是谢谢。
【解决方案3】:

似乎我终于解决了,我使用了广播接收器,发现了错误所在 - Calendar 将月份参数从 0 到 11,而不是我认为的 1-12,因为所有其他参数都是正常处理。所以我只是在五月底发布通知,而不是今天测试时。

无论如何,谢谢大家的帮助,非常感谢。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多