Well I have tried enough to look for the answer to the question mentioned above, but my efforts have been futile so far.
I have created an alarm with the help of the alarmmanager class which will fire up the notification at regular intervals of time(probably about 5 days).
Below is the code for the implementation of the alarm happening inside onClick() of a button.
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent notificationIntent = new Intent("android.media.action.DISPLAY_NOTIFICATION");
notificationIntent.addCategory("android.intent.category.DEFAULT");
PendingIntent broadcast = PendingIntent.getBroadcast(this, 100, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Calendar cal = Calendar.getInstance();
if(fromDateEtxt.getText().toString().length()>0) {
cal.add(Calendar.HOUR_OF_DAY, 10);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,cal.getTimeInMillis(), 5 * 24 * 60 * 60 * 1000, broadcast);
}
The code for the broadcast receiver.
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent notificationIntent = new Intent(context, NotificationActivity.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
stackBuilder.addParentStack(NotificationActivity.class);
stackBuilder.addNextIntent(notificationIntent);
PendingIntent pendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
Notification notification = builder.setContentTitle("Demo App Notification")
.setContentText("New Notification From Demo App..")
.setTicker("New Message Alert!")
.setSmallIcon(R.mipmap.ic_launcher)
.setContentIntent(pendingIntent).build();
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0, notification);
}}
The onClick() method apart from starting of the alarm changes the activity also. Now the problem I am facing is I dont know really how to stop the repeating alarm. I want to stop the alarm on a particular date. Secondly, I was confused whether to use the alarm.cancel for cancelling the alarm or to use another alarm for cancellation of the previous alarm as shown here. Apart from this, I wanted to know if the alarm could be cancelled from another activity or does the point seems unnecessary and the limit to the date could be set beforehand?
Related
I am creating a research app that should prompt the user 4 times a day to enter their mood - by sending a notification, which when clicked launches the correct Activity. I am able to schedule these notifications using AlarmManager, however only the last scheduled notification ever shows. So although I schedule them for 9AM, 2PM, 5PM, and 8PM, it only ever sends a notification at 8PM.
How can I get all of the scheduled notifications to show?
Here is my code for setting (one of) the alarms (from a notification manager class). Note that al alarms are set using the same instance of AlarmManager:
cal.setTimeInMillis(System.currentTimeMillis());
cal.set(Calendar.HOUR_OF_DAY, 9);
cal.set(Calendar.MINUTE, 0);
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
am.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), createPendingIntent(9, this));
Here is the createPendingIntent method (in the same notification manager class):
public static PendingIntent createPendingIntent(int hour, Context c){
Intent notificationIntent = new Intent(c, AlarmBroadcastReceiver.class);
notificationIntent.putExtra("time", hour);
PendingIntent pendingIntent = PendingIntent.getBroadcast(c, 0 , notificationIntent , PendingIntent.FLAG_UPDATE_CURRENT);
return pendingIntent;
}
Here is the BroadcastReceiver for the alarm:
public class AlarmBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
NotificationSender.createNotification(context);
}
}
And finally the createNotification method:
public static void createNotification(Context c){
Log.e("notif?", "creating");
Intent intent = new Intent(c, UpdateMoodActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
int notificationId = new Random().nextInt();
PendingIntent pendingIntent = PendingIntent.getActivity(c, 0, intent, 0);
NotificationCompat.Builder builder = new NotificationCompat.Builder(c, "com.lizfltn.phdapp.notifChannelID")
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setContentTitle("SoftMood")
.setContentText("Please record your mood")
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setContentIntent(pendingIntent)
.setAutoCancel(true);
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(c);
notificationManager.notify(notificationId, builder.build());
}
Yes I know this isn't the best-practice way of doing things, or even the neatest, but unfortunately I need to get code working ahead of writing good code :P
I've tried various configurations of setting the alarm, e.g. using elapsed realtime instead of RTC, only setting the alarm, setting the exact alarm, etc, but there might be something fundamental I'm not understanding about how those work.
Any help appreciated!
Can you try with same id in pending intent and notify.?
Notification id in createNotification() method is random id.
int notificationId = new Random().nextInt();
and id used in createPendingIntent method is 0.
PendingIntent pendingIntent = PendingIntent.getBroadcast(c, 0 , notificationIntent , PendingIntent.FLAG_UPDATE_CURRENT);
Can you try with using same value for second parameter of getBroadcast?
I want my user to set a time to receive a daily reminder from my app. In my ReminderActivity I create the PendingIntent and the Alarm Manager, and then in my Alarm Receiver class I create the notification inside onReceive(). I tried both the FLAG_CANCEL_CURRENT and FLAG_UPDATE_CURRENT flags when creating the pending intent but still when I am testing the app and changing the reminder time then sometimes the notification doesn't arrive at all, or it arrives only when the app is running in the background and the screen is on. I would greatly appreciate any thought or ideas.
ReminderActivity code:
private void setNotification() {
Calendar calendar = Calendar.getInstance();
Calendar now = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, chosenHour);
calendar.set(Calendar.MINUTE, chosenMinute);
calendar.set(Calendar.SECOND, 0);
//if user sets the alarm after their preferred time has already passed that day
if(now.after(calendar)) {
calendar.add(Calendar.DAY_OF_MONTH, 1);
}
Intent intent = new Intent(this, AlarmReceiver.class);
pendingIntent = PendingIntent.getBroadcast(ReminderActivity.this, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
alarmManager = (AlarmManager) getSystemService(Activity.ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pendingIntent);
}
Alarm Receiver code:
#Override
public void onReceive(Context context, Intent intent) {
Bitmap largeLogo = BitmapFactory.decodeResource(context.getResources(),
R.drawable.ptwired_logo);
//create local notification
NotificationManager notificationManager = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
Intent notificationIntent = new Intent(context, MainActivity.class);
//notificationIntent.putExtra("FromPTWired", true); //to track if user opens the app from the daily digest notification
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, notificationIntent, PendingIntent.FLAG_CANCEL_CURRENT);
Notification notification = new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.ptwired_logo)
.setLargeIcon(largeLogo)
.setContentTitle(context.getResources().getString(R.string.app_name))
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setContentIntent(pendingIntent)
.setContentText(REMINDER_TEXT)
.setAutoCancel(true)
.setOngoing(false)
.build();
notificationManager.notify(1, notification);
}
}
Probably an issue of Doze mode, take a look in Android restriction:
Doze restrictions
The following restrictions apply to your apps while in Doze:
Standard AlarmManager alarms (including setExact() and setWindow()) are deferred to the next maintenance window.
If you need to set alarms that fire while in Doze, use setAndAllowWhileIdle() or setExactAndAllowWhileIdle().
Alarms set with setAlarmClock() continue to fire normally — the system exits Doze shortly before those alarms fire.
am trying to schedule a notification with desired time and un the below code my desired time if after 10 seconds but i don't know why its showing up the notification instantly , am i doing anything wrong ? or missing anything please correct me if am wrong anywhere , and am using BlueStacks Emulator for testing (built version 4.4.2 Api 19)
notification = new NotificationCompat.Builder(this);
notification.setAutoCancel(true);
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent notificationIntent = new Intent("android.media.action.DISPLAY_NOTIFICATION");
notificationIntent.addCategory("android.intent.category.DEFAULT");
PendingIntent broadcast = PendingIntent.getBroadcast(this, 100, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Calendar cal = Calendar.getInstance();
cal.add(Calendar.SECOND, 10);
alarmManager.setExact(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), broadcast);
// why its showing up instantly insted of after 10 seconds
//alarmManager.setExact(AlarmManager.RTC_WAKEUP,20,broadcast);
Intent intent = new Intent(this , MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 , intent , PendingIntent.FLAG_UPDATE_CURRENT);
Intent switchIntent = new Intent(this, switchButtonListener.class);
PendingIntent pendingSwitchIntent = PendingIntent.getBroadcast(this, 0, switchIntent, 0);
notification.setSmallIcon(R.drawable.ok);
notification.setWhen(20);
notification.setTicker("you've got a meesage");
notification.setContentTitle("new message");
notification.setContentText("wanna take a ride?");
// notification.setContentIntent(pendingIntent);
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
notificationManager.notify(uniqueID, notification.build());
notification showing up instantly
When you call notificationManager.notify() in your last line, it displays the notification immediately.
I assume that you wanted to use an AlarmManager to display a notification and you don't quite understand what it does. An AlarmManager is used schedule an Intent to be broadcasted. An Intent can be used to perform a variety of task such as starting an Activity or Service. As far as i know it is not possible to use an Intent to display notification.
What you should be looking at is to use postDelayed() method in Handler class. For example:
handler = new Handler();
final Runnable r = new Runnable() {
public void run() {
// Create your notification using NotificationCompat.Builder
// and call notificationManager.notify()
}
};
handler.postDelayed(r, /*time to delay for in ms*/);
Edit: If you really want to use AlarmManager and broadcast to display a notification, you will need to extend a BroadcastReceiver and have it listen for your PendingIntent broadcast. Next, you will schedule the PendingIntent to be broadcasted using AlarmManager. When the AlarmManager fire off the PendingIntent after 10 seconds, your BroadcastReceiver will receive the broadcast and call notificationManager.notify() to display the notification. This is quite a roundabout way of displaying notification.
Is there a way to detect when a day was started or date or time changes (not changed by user, it is changed by system). Any BroadCastReciever to do it? I am using service to run it by every hour, But drains battery.
My requirement is to check when the day has started (when time changes to 12 AM) or time changes (hourly) I want to display the notification.
Create alarm set on a specified time say 00 hours in your case, using AlarmManager and BroadcastReceiver. And you will receive a brodcast on every new day.
private void setAlarm(Calendar targetCal){
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, targetCal.getTimeInMillis(), pendingIntent);
}
For further reference :
http://android-er.blogspot.in/2012/05/create-alarm-set-on-specified-time.html
or you can use ScheduledExecutorService to schedule and execute a task http://developer.android.com/reference/java/util/concurrent/ScheduledExecutorService.html
This is quite simple to do.
Step 1
Use the AlarmManager to fire up a BroadcastReceiver periodically..
private void showNotification() {
Intent alarmIntent = new Intent(this, NotificationReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 50000, pendingIntent);
}
Step 2
In the onReceive() do the checking when the time is 00 hours of the day, create a notification and show it.
public class NotificationReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Calendar now = GregorianCalendar.getInstance();
// This is where you check when you want to show the notification
if(now.get(Calendar.HOUR_OF_DAY) == 0){
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle(context.getResources().getString(R.string.message_box_title))
.setContentText(context.getResources().getString(R.string.message_timesheet_not_up_to_date));
Intent resultIntent = new Intent(context, MainActivity.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
stackBuilder.addParentStack(MainActivity.class);
stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.setContentIntent(resultPendingIntent);
NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(1, mBuilder.build());
}
}
}
Step 3
Do forgot to register the custom BroadcastReceiver is Manifest
<receiver
android:name="com.example.NotificationReceiver"
android:process=":remote" />
Hi I am new to notifications,
I wrote this code for notifications.
PendingIntent pendingIntent = PendingIntent.getActivity(context, leadidforstatus,
myIntent, Intent.FLAG_ACTIVITY_NEW_TASK);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.noti)
.setContentTitle("LMS notification")
.setContentIntent(pendingIntent)
.setContentText(intent.getStringExtra("messagenotify"))
.setAutoCancel(true);
i = (int) System.currentTimeMillis();
NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(i, mBuilder.build());
In that I set one list of notifications. In that some displayed and some not displayed. But I want to cancel all un shown notifications.
I used mNotificationManager.cancleAll() but that is cancel only shown notifications.
thanks in advance.
I think the problem here is that The Notification is launched immediately after creating it and your not using the AlarmManager to schedule this Notification.
Solution Should be to schedule Alarms via an AlarmManager which will trigger the Notification Code above.
This requires 3 parts:
Register a BroadCastReceiver & Build a Notification when its triggered:
public class UtilityReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// .. Here is where you really want to build the notification and notify
// This will be triggered by the AlarmManager from the Code below
PendingIntent pendingIntent = PendingIntent.getActivity(context, leadidforstatus, myIntent, Intent.FLAG_ACTIVITY_NEW_TASK);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.noti)
.setContentTitle("LMS notification")
.setContentIntent(pendingIntent)
.setContentText(intent.getStringExtra("messagenotify"))
.setAutoCancel(true);
i = (int) System.currentTimeMillis();
NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(i, mBuilder.build());
}
Schedule an Alarm with the AlarmManager to send a BroadCast which the Receiver above is listening for:
// Create an Intent to Launch
Intent notificationIntent = new Intent(context, UtilityReceiver.class);
// Use a Pending Intent to Launch the Alarm
PendingIntent notificationPendingIntent = PendingIntent.getBroadcast(context,
PendingIntent.FLAG_ONE_SHOT, notificationIntent, Intent.FILL_IN_DATA);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, timeForAlarmInMillis, notificationPendingIntent);
Then when you encounter the situation when you no longer want notifications to show for your app, you tell the AlarmManager to remove them from its queue of Alarms by Rebuilding the pending Intent and using AlarmManager to Cancel it.
// Create an Intent to Launch
Intent notificationIntent = new Intent(context, UtilityReceiver.class);
// Use a Pending Intent to Launch the Alarm
PendingIntent notificationPendingIntent = PendingIntent.getBroadcast(context,
PendingIntent.FLAG_ONE_SHOT, notificationIntent, Intent.FILL_IN_DATA);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
// *********Important this will cancel all the Matching PendingIntents
alarmManager.cancel(notificationPendingIntent);
Good Luck, and be sure to register your Receiver in your Activity or Manifest.
NotificationManager maintains list of all notification mNotificationList and performs cancel or cancelAll operations on this list
I tried searching in Google source code of NotificationManager.java and NotificationManagerService.java in notify(),enqueueNotificationWithTag() and cancelAllNotification() But there is no implementation to cancel previously unshown notification
As per your comment, if your user is deleted and his notification arrives then user is already deleted so notification has no meaning
i = (int) System.currentTimeMillis();
NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(i, mBuilder.build());
// i should be Id for this notification, i think you want to pass
// time in mili second here
I think you are searching similar to this,
How to dismiss notification after action has been clicked
Just check the answer on that post. Use the id to cancel that particular Notification
I think the id part in your code is this,
i = (int) System.currentTimeMillis();