【问题标题】:Bug when firing notification using AlarmManager at specific time every day每天在特定时间使用 AlarmManager 触发通知时的错误
【发布时间】:2014-07-02 23:15:15
【问题描述】:

在我的应用程序中,用户使用时间选择器设置警报,以通知他们何时使用该应用程序。当他们设置提醒时,它将每 24 小时通知用户一次。我已经使用 AlarmManager 和 Service 来解决这个问题。当我设置时间时,我每 24 小时收到一次通知,但有时我会一次又一次地随机收到通知。这是一个我无法调试的错误,我不知道问题出在哪里。

这就是我的做法:

设置提醒并取消它是我的代码: 我使用 AlarmManager 来设置时间。

private void setReminder(){
    Calendar calendar = Calendar.getInstance();
    Calendar currentCalendar = Calendar.getInstance();
    calendar.set(Calendar.HOUR_OF_DAY, timePicker.getCurrentHour());
    calendar.set(Calendar.MINUTE, timePicker.getCurrentMinute());

    SimpleDateFormat sdf = new SimpleDateFormat(TIME_FORMAT, Locale.US);
    String time = sdf.format(calendar.getTime());
    SavingData.setReminder(time, true);

    long intendedTime = calendar.getTimeInMillis();
    long currentTime = currentCalendar.getTimeInMillis();

    alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
    Intent intent = new Intent(this, MyReceiver.class);
    pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);

    if((intendedTime >= currentTime) == false){
        // This will set the alarm for the next day, if time is below intentedTime
        calendar.add(Calendar.DAY_OF_MONTH, 1);
        intendedTime = calendar.getTimeInMillis();
    }

    alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, intendedTime, AlarmManager.INTERVAL_DAY, pendingIntent);

    Toast.makeText(this, "Alarm Scheduled!", Toast.LENGTH_LONG).show();
}

private void cancelId() {
    Calendar calendar = Calendar.getInstance();
    calendar.set(Calendar.HOUR_OF_DAY, timePicker.getCurrentHour());
    calendar.set(Calendar.MINUTE, timePicker.getCurrentMinute());

    // Time format to String
    SimpleDateFormat sdf = new SimpleDateFormat(TIME_FORMAT, Locale.US);
    String time = sdf.format(calendar.getTime());
    SavingData.setReminder(time, false);

    alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE); 
    Intent intent = new Intent(this, MyReceiver.class);
    pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);

    // If the alarm has been set, cancel it.
    if (alarmManager!= null) {
        alarmManager.cancel(pendingIntent);
        Toast.makeText(this, "Cancel Alarm!", Toast.LENGTH_SHORT).show();
    }
}

我使用广播接收器:

public class MyReceiver extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {
    Toast.makeText(context, "MyReceiver!", Toast.LENGTH_SHORT).show();
    Intent service = new Intent(context, MyService.class);
    context.startService(service);
}

}

下面是我的服务类。在我的服务类中,我使用通知管理器创建通知信息。

 public class MyService extends Service {
private static final int notificationID = 0;

@Override
public IBinder onBind(Intent intent) {
    // TODO Auto-generated method stub
    return null;
}

@Override
public void onCreate() {
    // TODO Auto-generated method stub
    super.onCreate();
}

@Override
@Deprecated
public void onStart(Intent intent, int startId) {
    // TODO Auto-generated method stub
    super.onStart(intent, startId);
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    NotificationManager notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);

    Intent notificationIntent = new Intent(this, MainActivity.class);
    PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);

    int icon = R.drawable.icon;
    String tickerText = "HELLO";
    long when = System.currentTimeMillis();
    String contentTitle = "How Are You";
    String contentText = "Time to use the App";
    // Define sound URI, the sound to be played when there's a notification
    Uri soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);

    Notification notification = new NotificationCompat.Builder(this)
    .setContentTitle(contentTitle)
    .setContentText(contentText)
    .setSmallIcon(icon)
    .setTicker(tickerText)
    .setWhen(when)
    .setContentIntent(pendingIntent)
    .setSound(soundUri)
    .build();

    notificationManager.notify(notificationID, notification);
    return super.onStartCommand(intent, flags, startId);
}

@Override
public void onDestroy() {
    // TODO Auto-generated method stub
    super.onDestroy();
}

}

【问题讨论】:

  • 如果您使用 adb 查看警报,它可能会帮助您调试。 stackoverflow.com/questions/6522792/…
  • 除了 Jim 概述的问题之外,您使用的 RTC_WAKEUP 没有 WakefulBroadcastReceiver(或我的 WakefulIntentService),这是不可靠的。此外,您正在泄漏服务 - 请在没有更多工作要做时停止服务。

标签: java android service notifications


【解决方案1】:

您的服务在死机时或在其他时间获得 Android 系统重启“空”意图,而您没有考虑这些意图。每当它收到意图时,您都会发送通知。来自文档:

intent 提供给 startService(Intent) 的 Intent,如给定。这可能 如果服务在其进程结束后重新启动,则为 null 离开了,它之前已经返回了任何东西,除了 START_STICKY_COMPATIBILITY。

如果您检查空意图或其他特定于警报意图的内容,您的问题应该会消失。

【讨论】:

  • 您能告诉我我必须修改代码的哪个位置来解决问题吗?如何检查空意图?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多