简体   繁体   English

每天在特定时间使用AlarmManager触发通知时的错误

[英]Bug when firing notification using AlarmManager at specific time every day

In my app a timepicker is used by the user to set an alarm to notify them on when to use the app. 在我的应用程序中,用户使用时间选择器设置警报,以通知他们何时使用该应用程序。 When they set the reminder it will notify the user every 24 hours. 当他们设置提醒时,它将每24小时通知用户。 I have used AlarmManager and Service to solve the problem. 我已经使用AlarmManager和Service解决了该问题。 When I set the time I get notification every 24 hours, but sometimes I keep getting notifications randomly again and again. 设置时间后,我每24小时就会收到通知,但有时我会不断地一次又一次地收到通知。 This is an error I can't debug and I don't know where the problem is. 这是我无法调试的错误,我也不知道问题出在哪里。

This is how I have done: 这是我做的事情:

To set an Reminder and cancel it here is my code: I use AlarmManager to set the Time. 要设置提醒并取消提醒,这是我的代码:我使用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();
    }
}

I use BroadCastReceiver: 我使用BroadCastReceiver:

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

} }

Below is my Service class. 以下是我的服务班级。 In my service class I create the notification information using notification manager. 在服务类中,我使用通知管理器创建通知信息。

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

} }

Your service is getting Android system restart "null" intents when it dies or at other times and you are not accounting for those. 您的服务在Android系统死机时或在其他时间使Android系统重新启动“空”意图,而您并未对此进行说明。 You send a notification any time it receives an intent. 您可以在收到意图时随时发送通知。 From the docs: 从文档:

intent The Intent supplied to startService(Intent), as given. intent提供给startService(Intent)的Intent。 This may be null if the service is being restarted after its process has gone away, and it had previously returned anything except START_STICKY_COMPATIBILITY. 如果服务在其进程消失后正在重新启动,并且它先前已返回除START_STICKY_COMPATIBILITY以外的任何内容,则该值为null。

If you check for null intents or other content specific to your alarm intent your problem should go away. 如果检查空意图或特定于警报意图的其他内容,则问题将消失。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM