Android通知会随机弹出

时间:2015-01-15 09:51:45

标签: android notifications alarmmanager

我想在用户选择并同时每天重复播放时弹出通知。我设置了这样的通知:

NotifyActivity:

public void setAlarm() {
    AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
    Intent alarmIntent = new Intent(NotifyActivity.this, AlarmReceiver.class);
    PendingIntent pendingIntent = PendingIntent.getBroadcast(NotifyActivity.this, 1, alarmIntent, PendingIntent.FLAG_ONE_SHOT);
    Calendar alarmStartTime = Calendar.getInstance();
    alarmStartTime.set(Calendar.HOUR_OF_DAY, hour);
    alarmStartTime.set(Calendar.MINUTE, minute);
    alarmManager.set(AlarmManager.RTC_WAKEUP, alarmStartTime.getTimeInMillis(), pendingIntent);
    AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.setTitle("Message Sent!").setCancelable(false).setNegativeButton("Close", new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int id) {
            dialog.cancel();
        }
    });
    AlertDialog alert = builder.create();
    alert.setTitle("TITLE");
    alert.setMessage("Notification was set.");
    alert.show();
}

AlarmReciever:

@Override
public void onReceive(Context context, Intent intent) {
    PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
    PowerManager.WakeLock wakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK, "NotificationService");
    wakeLock.acquire();
    Intent service1 = new Intent(context, AlarmService.class);
    context.startService(service1);
}

AlarmService:

@Override
public void onStart(Intent intent, int startId) {
    super.onStart(intent, startId);
    Context context = this.getApplicationContext();
    notificationManager = (NotificationManager) context.getSystemService(context.NOTIFICATION_SERVICE);
    Intent mIntent = new Intent(this, MainActivity.class);
    pendingIntent = PendingIntent.getActivity(context, 0, mIntent, PendingIntent.FLAG_ONE_SHOT);
    Uri soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
    NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
    builder.setContentTitle("TITLE");
    builder.setContentText("TEXT");
    builder.setSmallIcon(R.drawable.logo);
    builder.setSound(soundUri);
    builder.setContentIntent(pendingIntent);

    notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
    notificationManager.notify(NOTIFICATION_ID, builder.build());

    PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
    PowerManager.WakeLock wakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK
            | PowerManager.ACQUIRE_CAUSES_WAKEUP | PowerManager.ON_AFTER_RELEASE, "NotificationService");
    wakeLock.acquire(10000);
    WakeLock wl_cpu = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MyCpuLock");
    wl_cpu.acquire(10000);
    wakeLock.release();

    //set next alarm after 24 hours
    AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
    Intent alarmIntent = new Intent(AlarmService.this, AlarmReceiver.class);
    PendingIntent pendingIntent = PendingIntent.getBroadcast(AlarmService.this, 1, alarmIntent,
            PendingIntent.FLAG_ONE_SHOT);
    alarmManager.setExact(AlarmManager.RTC_WAKEUP, Calendar.getInstance().getTimeInMillis() + 86400000, pendingIntent);
}

一切都很好。我在设置时收到通知。但也可以随机获得相同的通知。如何摆脱这些随机通知?有什么想法吗?

编辑: 我更新了我的代码并将警报设置为简单而不是setRepeating。弹出旧通知时,我在服务中设置了新警报。但我仍然会随机收到通知。在我设置的时间弹出第一个通知,其他人在24小时后但在几小时,40分钟或其他随机时间后弹出。我试图设置alarmManager.setExact它只来自api 19,但我遇到了同样的问题。我的targetSdkVersion现在设置为18。

编辑2:如果我只在NotifyActivity中设置闹钟并删除最后五行AlarmService,它也会抛出多个通知。我认为它应该只扔一个。

2 个答案:

答案 0 :(得分:0)

如果打算不唤醒手机,请忽略下面的文字(因此,我认为唤醒锁对您的应用程序非常有用)。如果您想让应用程序即使在手机睡眠时也能正常工作,那么请阅读它:

尝试使用RTC_WAKE_UP而不是RTC。当手机睡觉时,它不会以这种方式醒来。

此外,我发现你可能有问题让你的手机保持清醒状态。它可以在服务完成之前进入睡眠状态。 在onReceive()中使用WakefulBroadcastReceiver或创建WakeLock。 这将确保您的电话在服务期间处于清醒状态。

WakefulBroadcastReceiver是第二件事的最佳选择,关于唤醒锁 - 你可以在google上查看一些示例,说明如何将警报管理器与唤醒锁使用。 Ofc,你的服务可以完成它的工作,但有时睡眠可能会出现,所以我建议你实施它,即使你的测试没有显示问题,更好的是保持安全。

编辑:

选中,你可以使用PendingIntent.FLAG_ONE_SHOT而不是PendingIntent.FLAG_CANCEL_CURRENT,但不能在你设置闹钟的待处理中,但是在那里你设置你的通知。它应该工作得很好!

编辑2:

另外,我建议您更改请求编号。等待意图不会被这种方式压倒。

例如:

在AlarmService中:

pendingIntent = PendingIntent.getActivity(context, 0, mIntent, PendingIntent.FLAG_ONE_SHOT);

在setAlarm()中:

PendingIntent pendingIntent = PendingIntent.getBroadcast(NotifyActivity.this, 1, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);

我不确定这两者是如何协同工作的,有可能它们不能被覆盖,但我认为这样做更安全。 如果您希望创建更多待处理的意图以便不被覆盖,则可以使用SharedPreferences保持int number或date base int,每次创建Pending Intent时将其递增并将其作为参数放入其中。在我的应用程序中它工作正常。

答案 1 :(得分:0)

请注意,文档here表明"从API 19开始,所有重复警报都不准确。如果您的应用程序需要精确的交付时间,那么它必须使用一次性精确警报,每次重新安排如上所述。 targetSdkVersion早于API 19的旧应用程序将继续拥有所有警报,包括重复警报,视为确切的"。

也许这导致了这个问题?