I want to update the content for a reminder after it has been added before being received by the user. After setting a reminder through AlarmManager using the data stored in sqlite database, the notification from the reminder set only shows the data, title and description, that was first added, not any updated data stored corresponding to the ID as primary key.
Things I have tried:
cancelling the pending intent for the reminder then setting it again after updating the data stored in the database but it still displays the same result.
using an activity for adding data to be stored in the database to set a reminder and using another activity for updating this data as an attempt to update the reminder content with the same ID issued. One result shows two notifications received, one with initial title and description, and the other with updated information.
Currently, the methods I use to set and cancel a reminder is in my Adapter class for Recyclerview. I am stuck on updating although adding and cancel works fine.
Update: Now I use two separate activities for the add and update reminder functions.
For adding a reminder:
databaseManager.addReminder(titlePicked, descriptionPicked, timePicked, datePicked, dateTimePicked);
startActivity(new Intent(getApplicationContext(), MainActivity.class));
setAlarm();
private void setAlarm() {
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(getApplicationContext(), ReminderReceiver.class);
intent.putExtra("DateTime", dateTimePicked);
intent.putExtra("NotifID", remId);
intent.putExtra("Title", titlePicked);
intent.putExtra("Description", descriptionPicked);
PendingIntent addIntent = PendingIntent.getBroadcast(this, remId, intent, 0);
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, Date.parse(dateTimePicked), addIntent);
}
For updating a reminder:
databaseManager.updateReminder(remindId, titlePicked2, descriptionPicked2, timePicked, datePicked, dateTimePicked);
startActivity(new Intent(getApplicationContext(), MainActivity.class));
updateAlarm();
private void updateAlarm() {
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(getApplicationContext(), ReminderReceiver.class);
intent.putExtra("DateTime", dateTimePicked);
intent.putExtra("NotifID", remindId);
intent.putExtra("Title", titlePicked2);
intent.putExtra("Description", descriptionPicked2);
PendingIntent updateIntent = PendingIntent.getBroadcast(this, remindId, intent, 0);
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, Date.parse(dateTimePicked), updateIntent);
}
Receiver class:
public class ReminderReceiver extends BroadcastReceiver {
private static final String CHANNEL_ID = "CHANNEL_REMIND";
String DateTimeChoice, TitleChoice, DescriptionChoice;
int notificationID;
#Override
public void onReceive(Context context, Intent intent) {
DateTimeChoice = intent.getStringExtra("DateTime");
notificationID = intent.getIntExtra("NotifID", 0);
TitleChoice = intent.getStringExtra("Title");
DescriptionChoice = intent.getStringExtra("Description");
Intent mainIntent = new Intent(context, ViewReminder.class);
mainIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent contentIntent = PendingIntent.getActivity(context, notificationID, mainIntent, 0);
NotificationManager notificationManager =
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// For API 26 and above
CharSequence channelName = "My Notification";
int importance = NotificationManager.IMPORTANCE_DEFAULT;
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, channelName, importance);
notificationManager.createNotificationChannel(channel);
}
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, CHANNEL_ID)
.setSmallIcon(android.R.drawable.ic_dialog_info)
.setContentTitle(TitleChoice)
.setContentText(DescriptionChoice)
.setContentIntent(contentIntent)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setColor(context.getResources().getColor(R.color.purple_700))
.setAutoCancel(true);
notificationManager.notify(notificationID, builder.build());
}
Adapter class:
int remindId = reminder.getReminderId();
databaseManager = new DatabaseManager(holder.view.getContext());
sqLiteDB = databaseManager.getWritableDatabase();
public void onClick(View view) {
Reminder reminder = remindList.get(holder.getAdapterPosition());
PopupMenu popupMenu = new PopupMenu(view.getContext(), view);
popupMenu.setGravity(Gravity.END);
popupMenu.getMenu().add("Edit").setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem menuItem) {
Intent intent = new Intent(view.getContext(), UpdateReminderActivity.class);
intent.putExtra("reminderId", remindId);
intent.putExtra("title", reminder.getReminderTitle());
intent.putExtra("definition", reminder.getReminderDefinition());
view.getContext().startActivity(intent);
return true;
}
});
For updating a pending intent, you need to use FlAG_UPDATE_CURRENT with the same id you used earlier to set the initial intent.
If you want to update the alarm associated with that pending intent, you need to cancel the old alarm & then the old PendingIntent. Then create a new PendingIntent like this,
PendingIntent updateIntent = PendingIntent.getBroadcast(this, remindId, intent,PendingIntent.FLAG_UPDATE_CURRENT);
and set it to the alarm.
Related
I create multiple notifications using AlarmManager. Each notification pop-ups correctly and I would like to cancel each of these notification separately. I have an AlarmReceiver that creates the notification and sets the unique id for it. I'm sending the unique id in the intent (via putExtra). This way, I can retrieve it in the NotificationReceiver and cancel the notification. However, it is not working.
Do you know why I always get the default value when I use intent.getIntExtra("UNIQUE_ID_NAME",0) ?
Is it a proper way to achieve the goal of cancelling these notifications ?
Here is my code:
MainActivity class:
#Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, ReminderBroadcast.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 0, intent, 0);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
long ctime = System.currentTimeMillis();
long tensec = 1000 * 5;
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, ctime+tensec, 1000*10 , pendingIntent);
}
AlarmReceiver Class:
#Override
public void onReceive(Context context, Intent intent) {
int notification_id = generateRandom();
Intent activityIntent = new Intent(context, MainActivity.class);
activityIntent.putExtra(NotificationReceiver.UNIQUE_ID_NAME, notification_id);
PendingIntent contentIntent = PendingIntent.getActivity(context, 0, activityIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Intent bYesIntent = new Intent(context, NotifReceiver.class);
bYesIntent.putExtra(NotificationReceiver.YES_ACTION_ID, "yesID");
PendingIntent actionYesIntent = PendingIntent.getBroadcast(context, 0, bYesIntent, 0);
Intent bNoIntent = new Intent(context, NotifReceiver.class);
bNoIntent.putExtra(NotificationReceiver.NO_ACTION_ID, "noID");
PendingIntent actionNoIntent = PendingIntent.getBroadcast(context, 0, bNoIntent, 0);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, "channel1")
.setSmallIcon(R.drawable.ic_launcher_background)
.setContentTitle("Notif")
.setContentText("Text")
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setContentIntent(contentIntent)
.addAction(R.mipmap.ic_launcher, "YES", actionYesIntent)
.addAction(R.mipmap.ic_launcher, "NO", actionNoIntent)
.setAutoCancel(true);
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
notificationManager.notify(notification_id, builder.build());
}
public int generateRandom(){
Random random = new Random();
return random.nextInt(9999 - 1000) + 1000;
}
NotificationReceiver Class:
public class NotificationReceiver extends BroadcastReceiver {
public static String YES_ACTION_ID = "YesID";
public static String NO_ACTION_ID = "NoID";
public static String UNIQUE_ID_NAME = "notification_id";
#Override
public void onReceive(Context context, Intent intent) {
int notification_id= intent.getIntExtra(UNIQUE_ID_NAME,0);
System.out.println("Notif ID: " + notification_id); // here always is 0;
String actionYes = intent.getStringExtra(YES_ACTION_ID);
String actionNo = intent.getStringExtra(NO_ACTION_ID);
if(actionYes!=null){
Toast.makeText(context, "YES", Toast.LENGTH_SHORT).show();
}
if(actionNo!=null){
Toast.makeText(context, "NO", Toast.LENGTH_SHORT).show();
}
NotificationManager manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
manager.cancel(notification_id);
}
}
I solved this problem by updating current intent and request code. Notifications are reusing the same Intent so adding FLAG_UPDATE_CURRENT should be used to be able to cancel all notification separately.
For contentIntent:
PendingIntent contentIntent = PendingIntent.getActivity(context, notification_id, activityIntent, PendingIntent.FLAG_UPDATE_CURRENT);
For actionYesIntent
PendingIntent actionYesIntent = PendingIntent.getBroadcast(context, notification_id, bYesIntent, PendingIntent.FLAG_UPDATE_CURRENT);
For actionNoIntent:
PendingIntent actionNoIntent = PendingIntent.getBroadcast(context, notification_id, bNoIntent, PendingIntent.FLAG_UPDATE_CURRENT);
You are not adding notification_id for cases when Yes or No button is pressed,
Intent bYesIntent = new Intent(context, NotifReceiver.class);
bYesIntent.putExtra(NotificationReceiver.UNIQUE_ID_NAME, notification_id);
bYesIntent.putExtra(NotificationReceiver.YES_ACTION_ID, "yesID");
PendingIntent actionYesIntent = PendingIntent.getBroadcast(context, 0, bYesIntent, 0);
Intent bNoIntent = new Intent(context, NotifReceiver.class);
bNoIntent.putExtra(NotificationReceiver.UNIQUE_ID_NAME, notification_id);
bNoIntent.putExtra(NotificationReceiver.NO_ACTION_ID, "noID");
PendingIntent actionNoIntent = PendingIntent.getBroadcast(context, 0, bNoIntent, 0);
This method is from my Helper class for sending notification. I call this method in for loop.
synchronized public void sendNotification(String app, String actionId, String notificationTitle, String notificationText) {
if (SessionManager.isUserLoggedIn()) {
//Initial validation before sending the notifications
if (NullCheckUtils.isEmpty(context)) return;
//If notification is already sent, this action id will be available in map, so need to send notification again
if (notificationMap.get(actionId) != null) return;
notificationMap.put(actionId, notificationCounterId);
//Preparing notification manager for sending notifications
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
//Customizing notification content's to be displayed
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context, channelId)
.setSmallIcon(R.drawable.ic_launcher)
.setAutoCancel(true)
.setContentTitle(notificationTitle)
.setStyle(new NotificationCompat.BigTextStyle().bigText(notificationText))
.setLargeIcon(icon)
.setChannelId(channelId)
.setContentText(notificationText);
//Defualt loading of Intent when the body of notification is clicked
Intent intent = new Intent(context, FunctionMenuActivity.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
stackBuilder.addNextIntent(intent);
PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.setContentIntent(resultPendingIntent);
Intent openIntent = new Intent(context, NotificationReceiver.class);
openIntent.putExtra("notificationId", notificationMap.get(actionId) + "");
openIntent.setAction(Constants.Notification.YES_ACTION);
PendingIntent pendingIntentYes = PendingIntent.getBroadcast(context, 1, openIntent, PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.addAction(R.drawable.ic_launcher, context.getString(R.string.open), pendingIntentYes);
Intent dismissIntent = new Intent(context, NotificationReceiver.class);
dismissIntent.putExtra("notificationId", actionId);
dismissIntent.setAction(Constants.Notification.STOP_ACTION);
PendingIntent pendingIntentNo = PendingIntent.getBroadcast(context, 1, dismissIntent, PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.addAction(R.drawable.ic_launcher, context.getString(R.string.close), pendingIntentNo);
System.out.println("Data Check:" + notificationMap.get(actionId) + " : " + actionId);
notificationManager.notify(notificationMap.get(actionId), mBuilder.build());
notificationCounterId++;
}
}
Followed by my receiver class, where I receive the action events of Yes & Stop action events. In both case I am getting notificationId same everytime. Expected result is to get the unqiue notification id, which I am passing in the intent bundle. Could anyone explain me, what am I doing wrong here.
public class NotificationReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (Constants.Notification.YES_ACTION.equals(action)) {
String notificationId = intent.getStringExtra("notificationId");
context.startActivity(new Intent(context, FunctionMenuActivity.class));
Toast.makeText(context, "YES CALLED", Toast.LENGTH_SHORT).show();
System.out.println("Data Check:"+action+" : "+notificationId);
} else if (Constants.Notification.STOP_ACTION.equals(action)) {
String notificationId = intent.getStringExtra("notificationId");
NotificationHelper.getInstance().removeNotification(notificationId);
Toast.makeText(context, "STOP CALLED: " + notificationId, Toast.LENGTH_SHORT).show();
System.out.println("Data Check:"+action+" : "+notificationId);
}
}
}
Upon changing the request id of pending intent, the issue got resolved. Earlier I was passing request id as 0(Now replaced with notificationCounterId) all the time.
PendingIntent pendingIntentYes = PendingIntent.getBroadcast(context, notificationCounterId, openIntent, PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.addAction(R.drawable.ic_launcher, context.getString(R.string.open), pendingIntentYes);
I am trying to implement multiple notifications for each reminder I have in my app. I found some leads around here that it could be achieved using unique id per each notification but it is not working I get only one notification which is overwritten by the last one set. Also I would like know how is it possible to keep the notification intact after device is rebooted please. Here is my code
//call notification activation Intent
Intent intent = new Intent(getBaseContext(), AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(getBaseContext(), RQS_1, intent, 0);
AlarmManager alarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
AlarmReceiver class
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
//creating unique id for each specific notification
int ID = (int) ((new Date().getTime()/1000L) % Integer.MAX_VALUE);
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
Intent notification = new Intent(context,MainActivity.class);
notification.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pi = PendingIntent.getActivity(context,0,notification,0);
Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder mynotification = new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.ic_date_range_black_48dp)
.setContentTitle("note taker")
.setContentText("you have a reminder about a note")
.setAutoCancel(true)
.setContentIntent(pi)
.setSound(defaultSoundUri)
.setVibrate(new long[]{1000,1000,1000,1000,1000});
notificationManager.notify(ID,mynotification.build());
}
}
I found some leads around here that it could be achieved using unique id per each notification but it is not working i get only one notification which is overwritten by the last one set
I think the problem lies not in your notification, but in your AlarmManager.
Try using different ID for each PendingIntent, and set the flag to PendingIntent.FLAG_ONE_SHOT.
Your calling intent should look like this:
//call notification activation Intent
Intent intent = new Intent(getBaseContext(), AlarmReciever.class);
int RQS_1 = (int) System.currentTimeMillis();
PendingIntent pendingIntent = PendingIntent.getBroadcast(getBaseContext(), RQS_1, intent, PendingIntent.FLAG_ONE_SHOT);
AlarmManager alarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
Try to give different request code and PendingIntent.FLAG_UPDATE_CURRENT as Flag for Pending Intent and check like this,
PendingIntent pi = PendingIntent.getActivity(context, new Random().nextInt(1000000), notification, PendingIntent.FLAG_UPDATE_CURRENT);
Here there is an activity called grouchat. The messages are sent and received by gcmIntent class. In that class I have the code that issues the notification to the mobile.
In our app more than one event is there for groupchat. If I click the notification, it should take me to the right chat window, so I have passed the eventMO by putExtra parcelable. In the groupchat there is code to get a parcelable
The following is the code in groupchat activity:
eventMO = (EventMO) getIntent().getParcelableExtra("eventMo");
List<ChatMO> chatMOs = dbHelper.getGroupChatMessageForEvent(eventMO.getEventId());
The following code is in gcmIntend class to build the notification:
Intent groupChatActFrag = new Intent(getApplicationContext(), GroupChatActivity.class);
//here i have messageMO so i just set the eventid from messageMO to eventMO according to get the eventID in groupchat Activity
EventMO eventMO = new EventMO();
eventMO.setEventId(messageMO.getEventId());
groupChatActFrag.putExtra("eventMo", eventMO);
groupChatActFrag.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, groupChatActFrag, 0);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_dialog_info)
.setContentTitle(messageMO.getEventTitle())
.setStyle(new NotificationCompat.BigTextStyle().bigText(messageMO.getfromUserName()))
.setContentText(messageMO.getMessage())
.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION));
mBuilder.setContentIntent(contentIntent);
mBuilder.setAutoCancel(true);
Log.e("gcm","eventid"+messageMO.getEventId());
mNotificationManager.notify((int) (long) eventMO.getEventId(), mBuilder.build());
If I clicked the notification it throws a null pointer exception, because I get eventMO as null. Please tell me how to pass the current event id in GcmIntent class to groupchat activity.
I use this code in my projects
Notification
Intent intent = new Intent(context.getApplicationContext(), MainActivity.class);
intent.setAction(Intent.ACTION_VIEW);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(context.getApplicationContext(), id, intent, PendingIntent.FLAG_UPDATE_CURRENT);
Notification notification = new NotificationCompat.Builder(context)//
.setContentTitle(title == null ? context.getString(R.string.app_name) : title)//
.setContentText(message)//
.setStyle(new NotificationCompat.BigTextStyle().bigText(message))//
.setSmallIcon(R.drawable.ic_launcher)//
.setContentIntent(pendingIntent)//
.setTicker(context.getString(R.string.app_name))//
.build();
notification.defaults |= Notification.DEFAULT_ALL;
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Service.NOTIFICATION_SERVICE);
notification.flags |= Notification.FLAG_AUTO_CANCEL;
notificationManager.notify(id, notification);
In Activity check intent in onCreate and onNewIntent
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
if (getIntent() != null) {
checkIntent(getIntent());
}
}
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
checkIntent(intent);
}
private void checkIntent(Intent intent)
{
...
}
You need change getEvent Id to id of notification.
int notification_id = 123;
notificationManager.notify(notification_id, notification);
my code is
public class AlarmReceiver extends BroadcastReceiver {
public Notification mNotification = null;
public NotificationManager mNotificationManager = null;
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "time up!", Toast.LENGTH_SHORT).show();
mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
mNotification = new Notification(R.drawable.icon, "tip!",
System.currentTimeMillis());
mNotification.contentView = new RemoteViews(context.getPackageName(),
R.layout.notification);
mNotification.contentView.setTextViewText(R.id.tv_tip, "click to see the description");
Intent notificationIntent = new Intent(context,NotificationTip.class);
notificationIntent.putExtra("description", intent.getStringExtra("description")) ;
//notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent contentIntent = PendingIntent.getActivity(context, 0,
notificationIntent, 0);
mNotification.contentIntent = contentIntent;
mNotificationManager.notify(0, mNotification);
}
}
While when I click the item in notification ,I can't get to NotificationTip activity,so what's wrong with this code?
following line
Intent notificationIntent = new Intent(context,NotificationTip.class);
needs to be
Intent notificationIntent = new Intent("X");
Where X is the intent action name. this you have to add as intent filter in your android manifest file.