간단한 미리 알림 응용 프로그램을 개발하려고하는데 사용자가 미리 알림을 만들면 'AlarmManager '클래스를 통해 알람을 설정합니다. 알람을 설정하기 위해 알림의 식별자를 인 텐트 내부의 데이터베이스에 넣은 다음 해당 인 텐트를 보류중인 인 텐트에 넣습니다. 경보가 수신되면, 알림의 식별자는 수신 된 의도로부터 취해지고 데이터베이스에서 검색됩니다.AlarmManager가 이전 데이터와 함께 보류중인 인 텐트를 보냅니다.
이 접근법은 전혀 작동하지 않습니다. 일반적으로 잘 동작하지만 수신 된 인 텐트 내부에 들어있는 식별자가 오래된 것이고 모든 애플리케이션이 실패합니다. 이것은 무작위로 발생하며 일관된 재현 방법을 찾을 수 없습니다. 그것은 무작위 적 실패이기 때문에 나는 이것으로 완전히 잃어버린다. 내가 의도 한 것의 여분에서받는 식별자가 내가 경보를 설정 한 식별자가 아니기 때문에 그것은 완전히 불합리하다. 대신 과거에 해고 된 오래된 경보의 식별자입니다.
package bembibre.alarmfix.alarms;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import java.util.Calendar;
import bembibre.alarmfix.database.RemindersDbAdapter;
import bembibre.alarmfix.logging.Logger;
import bembibre.alarmfix.utils.GeneralUtils;
/**
* Created by Max Power on 12/08/2017.
*/
/**
* Sets alarms in the operating system for the reminders of this application.
*/
public class ReminderManager {
/**
* This is the key that identifies a metadata item that is attached to the intent of an alarm of
* a reminder for tracking it.
*/
public static final String EXTRA_ALARM_ID = "extra_alarm_id";
private Context mContext;
private AlarmManager mAlarmManager;
public ReminderManager(Context context) {
mContext = context;
mAlarmManager =
(AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
}
/**
* Part of the code that is responsible for setting an alarm.
*
* @param taskId data base identifier of the reminder.
* @param alarmId number that helps distinguishing each one of the alarms set for a same reminder.
* @param when when.
*/
public void setReminder(long taskId, long alarmId, Calendar when) throws AlarmException {
PendingIntent pi = getReminderPendingIntent(taskId, alarmId, PendingIntent.FLAG_UPDATE_CURRENT);
try {
this.setAlarm(pi, when);
Logger.log("An alarm has been set successfully for the reminder at " + GeneralUtils.format(when) + ". Reminder id: " + taskId);
} catch (Throwable throwable) {
Logger.log("The system doesn't let us to set an alarm for the reminder at " + GeneralUtils.format(when), throwable);
throw new AlarmException();
}
}
/**
* Unsets the alarm that would trigger for the reminder with the given database identifier.
* When calling this method, the reminder could have been erased from the database and it
* wouldn't be a problem. This method is only for unsetting its associated alarm from the
* system.
*
* @param taskId database identifier of the reminder.
* @param alarmId number that helps distinguishing each one of the alarms set for a same reminder.
* @param date date for logging purposes.
*/
public void unsetReminder(long taskId, long alarmId, String date) {
PendingIntent pi = getReminderPendingIntent(taskId, alarmId, PendingIntent.FLAG_UPDATE_CURRENT);
mAlarmManager.cancel(pi);
Logger.log("An alarm has been unset successfully for the reminder at " + date + ". Reminder id: " + taskId);
}
/**
* Returns the <code>PendingIntent</code> object that must be used for calling this application
* when a reminder's alarm triggers.
*
* @param taskId the number that identifies the associated reminder in the database.
* @param alarmId incremental identifier for each alarm of the same reminder.
* @param flag flag that controls the behaviour of the pending intent.
* @return the <code>PendingIntent</code> object.
*/
private PendingIntent getReminderPendingIntent(long taskId, long alarmId, int flag) {
Intent i = new Intent(mContext, OnAlarmReceiver.class);
i.putExtra(RemindersDbAdapter.KEY_ROWID, taskId);
i.putExtra(ReminderManager.EXTRA_ALARM_ID, alarmId);
PendingIntent pi = PendingIntent.getBroadcast(mContext, (int)taskId, i, flag);
return pi;
}
/**
* Sets the alarm in the operating system.
*
* @param operation
* @param when
*/
private void setAlarm(PendingIntent operation, Calendar when) throws Throwable {
/*
* The alarm must be set differently depending on the OS version. Anyway, we need the
* pending intent in order to know what was the reminder for which the alarm was fired, so
* then the correct notification will be shown.
*/
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
// Before Marshmallow, we can do this for setting a reliable alarm.
mAlarmManager.set(AlarmManager.RTC_WAKEUP, when.getTimeInMillis(), operation);
} else {
/*
* Starting from Marshmallow, it seems like this is the only way for setting a reliable
* alarm.
* If we use the "alarm clock" framework, the user will see a icon of an alarm clock.
* If we use the setExactAndAllowWhileIdle the user will see nothing, but the OS can
* delay alarms at some sort of situations.
*/
mAlarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, when.getTimeInMillis(), operation);
}
}
}
편집 : 내가 원하는 식별자로 응용 프로그램을 여는 통지에 대한 또 다른 대기 의도를 만들 때 문제가 발생하면 경보 화재는, 그러나, 그것은 보류에있을 때 식별자가 올바른 온다 알림을 터치 할 때 사용되는 의도입니다. 다음은이 작업을 수행하는 코드입니다.
private void makeNotification(Long rowId, String title, String body) {
android.app.NotificationManager mgr = (android.app.NotificationManager)context.getSystemService(NOTIFICATION_SERVICE);
Intent notificationIntent;
long notificationId;
if (rowId == null) {
notificationId = 0;
notificationIntent = new Intent(context, ReminderListActivity.class);
} else {
notificationId = rowId;
notificationIntent = new Intent(context, ReminderEditActivity.class);
notificationIntent.putExtra(RemindersDbAdapter.KEY_ROWID, rowId);
}
PendingIntent pi = PendingIntent.getActivity(context, 0, notificationIntent,
PendingIntent.FLAG_ONE_SHOT);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context)
.setSmallIcon(android.R.drawable.stat_sys_warning)
.setContentTitle(title)
.setContentText(body)
.setContentIntent(pi)
.setStyle(new NotificationCompat.BigTextStyle().bigText(body));;
Notification note = mBuilder.build();
note.defaults |= Notification.DEFAULT_SOUND;
note.flags |= Notification.FLAG_AUTO_CANCEL;
// An issue could occur if user ever enters over 2,147,483,647 tasks. (Max int value).
// I highly doubt this will ever happen. But is good to note.
int id = (int)((long)notificationId);
mgr.notify(id, note);
NotificationManager.setNotified(context, id);
}
편집 : 나는 항상 오류를 재현 할 수있는 적어도 하나의 사례를 발견했습니다. 단계 :
- 현재 날짜에 대한 알림을 생성합니다.
- 알림을 기다리는 중입니다. 현재 날짜로 설정되어 있으므로 알림이 거의 즉시 전송됩니다.
- 알림을 삭제하십시오.
- 알림을 삭제합니다 (알림을 삭제하지 않고).
- 현재 날짜에 대한 다른 미리 알림을 만듭니다.
- 알림을 기다립니다.
- 알림을 클릭하여 이동합니다. 오류 가 재생됩니다.
고객님의 답변을 수락하십시오. 답이없는 질문 목록에서 질문을 제거합니다. –