Android Notifify - android

I've got an application that needs to show a notification of certain events in a day, depending on the event.
I know how to do it, if I need a service to stay running in the background, or it will run in the background getting these events on certain days.
private void Notificar(String descricaoEvento){
NotificationManager notifier = (NotificationManager)this.getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = new Notification(R.drawable.ic_launcher, "Novo evento no The Point Club", System.currentTimeMillis());
notification.flags |= Notification.DEFAULT_SOUND;
PendingIntent pIntent = PendingIntent.getActivity(this, 0, null, 0);
notification.setLatestEventInfo(this, "Title", descricaoEvento.toString(), pIntent);
notifier.notify(0x007, notification);
}
using this method to call when the right date!
Thanks for listening, I'll try to explain what I'm doing right: I'm making an application for a club party, and the application will show the next event of the celebrations when I open the application, but what I wish is that a notification is created in android notification bar, on which there is a party, serving as a reminder.
I use this code when I open the activity to list events:
Calendar c = Calendar.getInstance();
c.setTimeInMillis(System.currentTimeMillis());
int anoAtual= c.get(Calendar.YEAR);
long time = c.getTimeInMillis();
Intent it = new Intent("EXECUTAR_ALARME")
p = PendingIntent.getBroadcast(Eventos.this, 0, it, 0);
AlarmManager alarme = (AlarmManager) getSystemService(ALARM_SERVICE);
alarme.set(AlarmManager.RTC_WAKEUP, time, p);
the line
Intent it = new Intent("EXECUTAR_ALARME")
will call the class:
public class Alarm extends BroadcastReceiver{ #Override
public void onReceive(Context contexto, Intent intent) {
NotificationManager notifier =(NotificationManager) contexto.getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = new Notification(R.drawable.ic_launcher, "New event in Club", System.currentTimeMillis());
notification.flags |= Notification.DEFAULT_SOUND;
//Intent i = new Intent(this, Eventos.class);
PendingIntent pIntent = PendingIntent.getActivity(contexto, 0, null, 0);
notification.setLatestEventInfo(contexto, "Club", "Teste", pIntent);
notifier.notify(0x007, notification);
}
}
Now I want to know two things:
1 - How do I leave it running in the background without being open with the application.
2 This code only creates only an alarm, and I need to create multiple.
Thanks for the help.

Use AlarmManager to run a PendingIntent at your specific time. At that time, the intent that it stored in the PendingIntent should likely be a service if you're planning on creating a Notification to display to the user. If you could form this as a question, I may be able to help more, but it's unclear what you're trying to accomplish, and what you've managed to accomplish.
Additional Details
In your code, it looks like you're scheduling the alarm for right now, instead of at some time in the future. I'd suggest the following to create the alarm:
Calendar c = Calendar.getInstance();
// don't do this:
// c.setTimeInMillis(System.currentTimeMillis()); // This just sets the alarm time to "now"
// set the calendar to 8:00 pm:
c.set(Calendar.HOUR_OF_DAY, 20);
c.set(Calendar.MINUTE, 0);
long alarmTime = c.getTimeInMillis();
Intent it = new Intent(ServiceClass.getClass());
// Even though the docs say that the request code doesn't matter making it unique tells the alarmManager that it's a different PendingIntent
PendingIntent pendingIntent = PendingIntent.getService(this, 0, it, 0);
AlarmManager alarmMgr = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmMgr.set(AlarmManager.RTC_WAKEUP, alarmTime, pendingIntent); // set the first alarm for 8:00
c.set(Calendar.MINUTE, 30);
Intent it2 = new Intnt(ServiceClass.getClass());
PendingIntent pi2 = PendingIntent.getService(this, 0, it2, 0);
alarmMgr.set(AlarmManager.RTC_WAKEUP, alarmTime, pi2); // set the second alarm for 8:30
the line
Intent it = new Intent(ServiceClass.getClass());
will start the Class ServiceClass:
class ServiceClass extends Service {
#Override
public IBinder onBind(Intent intent) {
// TODO TRAVIS Auto-generated method stub
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) { // onStartCommand is run when the service is started by the AlarmManager
// build and set the notification here
NotificationManager notifMgr = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
// build notification
Notification notification = new Notification.Builder(getApplicationContext())
.setContentTitle("New mail from " + sender.toString())
.setContentText(subject)
.setSmallIcon(R.drawable.new_mail)
.setLargeIcon(aBitmap)
.build();
int ID = 0;
notifMgr.notify(ID++, notification); // use a unique id every time if you want multiple notifications (sounds like what you want, but not a best practice)
notification = new Notification.Builder(getApplicationContext())
.setContentTitle("New event from " + sender.toString())
.setContentText(subject)
.setSmallIcon(R.drawable.new_mail)
.setLargeIcon(aBitmap)
.build();
notifMgr.notify(ID++, notification); // add the second notification to the notification bar
return super.onStartCommand(intent, flags, startId);
}
}
Answers to your questions:
1 - By setting the alarm for sometime in the future, you're asking the OS to start your PendingIntent (in your case, send a Broadcast; in my exmaple above, a Service) at the time specified (that's why you need to set the time with the calendar to sometime in the future!)
2 - Creating multiple alarms is a matter of calling the alarm manager with different PendingIntent s scheduled at the appropriate time (for when you want them to fire). The same is true for Notification s, create multiple ones (with unique ids).

Related

Android AlarmManager only sending last scheduled notification

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?

Android local notification doesn't arrive every time

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.

Multiple Notifications not showing in android

In my android app I'm willing to show multiple notifications on a particular day,for this I'm using Alarm Manager and Broadcast Receiver problem is when I used alarm it worked fine but when I add notification builder to show the notification its not working
Here is my mainActivity
public static final String ACTION_ONE = "Hello, Test Message 1";
public static final String ACTION_TWO = "Hello, Test Message 2";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
AlarmManager alarmManager1 = (AlarmManager) getSystemService(ALARM_SERVICE);
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(System.currentTimeMillis());
Intent myIntent1 = new Intent(this, AlarmBroadCustReciver.class);
myIntent1.setAction(ACTION_ONE);
PendingIntent pendingIntent1 = PendingIntent.getBroadcast(this, 1253, myIntent1,
PendingIntent.FLAG_UPDATE_CURRENT);
// Set the time for first alarm here
cal.set(2015, 10, 20, 15, 55);
alarmManager1.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), pendingIntent1);
Intent myIntent2 = new Intent(this, AlarmBroadCustReciver.class);
myIntent2.setAction(ACTION_TWO);
PendingIntent pendingIntent2 = PendingIntent.getBroadcast(this, 1263, myIntent2,
PendingIntent.FLAG_UPDATE_CURRENT);
// Set the time for second alarm here
cal.set(2015, 10, 20, 15, 56);
alarmManager1.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), pendingIntent2);
// In this way set time for all the rest of the alarms
Here is BroadCastReceiver
public class AlarmBroadCustReciver extends BroadcastReceiver {
public static final String ACTION_ONE = "Hello, welcome to the Server1";
public static final String ACTION_TWO = "Hello, welcome to the Server2";
#Override
public void onReceive(Context context, Intent intent) {
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
builder.setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.mipmap.ic_launcher));
builder.setContentTitle(context.getString(R.string.app_name));
if (intent.getAction().equalsIgnoreCase(ACTION_ONE)) {
builder.setContentText("Alarm one");
} else {
builder.setContentText("Alarm two");
}
Notification notification = builder.build();
int notificationID = 0;
notificationManager.notify(notificationID, notification);
You need to pass different notification id for each Notification . If you pass same id (i.e., 0 in your case), the existed notification will be updated with the new data.
change the notification id: eg have a variable and increment it. notificationid++
I had a similar issue, I was creating multiple notifications with different IDs, however, when I clicked on one, only the first one opened the specific scree, all the sequential notifications were ignore (clicking on them didn't do anything, they were just dismissed). Then I tried to do this:
intent.setAction(context.getPackageName() + "." + notificationId);
Which means that each unique notification also carries its own unique Intent and in this case the Intents weren't ignored and each of them opened the needed screen. I must note that my Intents were the same (e.g. NoteDetails.class), so I guess I had to separate them somehow...i'm glad it worked anyways.
Box's answer was a nudge in the right direction for me.
I just had to change the requestCode in the PendingIntent I was passing to the AlarmManager, so it wasn't the same value.
Old code:
PendingIntent pI = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
New code:
PendingIntent pI = PendingIntent.getBroadcast(context, notificationId, intent, PendingIntent.FLAG_UPDATE_CURRENT);

Show status bar notification in certain time

I want to show the user notifications everyday in the same time. For now I only have this code:
My TimeAlarm.class that shows the notifications:
public class TimeAlarm extends BroadcastReceiver {
NotificationManager nm;
#Override
public void onReceive(Context context, Intent intent) {
nm = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
CharSequence from = "Nithin";
CharSequence message = "Crazy About Android...";
PendingIntent contentIntent = PendingIntent.getActivity(context, 0,
new Intent(), 0);
Notification notif = new Notification(R.drawable.ic_launcher,
"Crazy About Android...", System.currentTimeMillis());
notif.setLatestEventInfo(context, from, message, contentIntent);
notif.sound = Uri.parse("android.resource://"
+ context.getPackageName() + "/" + R.raw.test);
// r.play();
nm.notify(1, notif);
}
}
And initialization of the notifications to show every 5 seconds:
public void setRepeatingAlarm() {
Intent intent = new Intent(this, TimeAlarm.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0,
intent, PendingIntent.FLAG_CANCEL_CURRENT);
am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(),
(5 * 1000), pendingIntent);
}
Now my question is how should I modify this code to set the notification to repeat every day in certain time. Example every day in 14:36 o'clock?
The easy-but-inexact way is to change System.currentTimeMillis() to a calculation of 14:36 tomorrow, probably using a Calendar object:
Calendar cal=Calendar.getInstance();
cal.set(Calendar.HOUR_OF_DAY, 14);
cal.set(Calendar.MINUTE, 36);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
if (cal.getTimeInMillis() < System.currentTimeMillis()) {
cal.add(Calendar.DAY_OF_YEAR, 1);
}
I say "easy-but-inexact" because Android 4.4 has changed the behavior of setRepeating() to be inexact, once your android:targetSdkVersion is 19 or higher. If you need exact alarms, you will need to use setExact() and do your own "repeating" (by calling setExact() again when the alarm goes off). You would still use the same Calendar sort of calculation, just on every setExact() call.

Update time for AlarmManager (Android)

I use AlarmManager to display a notification for an event at the event date and time.
But how can I update the time the AlarmManager sends the PendingIndent to my app, when an event is updated?
When an event is created the following code is called:
public void setOneTimeAlarm() {
Intent intent = new Intent(this, TimerReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0,
intent, PendingIntent.FLAG_ONE_SHOT);
Calendar c = Calendar.getInstance();
c.set(Calendar.YEAR, year);
c.set(Calendar.MONTH, month);
c.set(Calendar.DAY_OF_MONTH, day-1);
c.set(Calendar.HOUR_OF_DAY, 18);
c.set(Calendar.MINUTE, 00);
long date = c.getTimeInMillis();
mAlarmManager.set(AlarmManager.RTC_WAKEUP, date, pendingIntent);
}
The indent called is TimerReciver:
#Override
public void onReceive(Context context, Intent intent) {
Log.v("TimerReceiver", "onReceive called!");
Intent notificationIntent = new Intent(context, ListTests.class);
PendingIntent contentIntent = PendingIntent.getActivity(context,
123, notificationIntent,
PendingIntent.FLAG_CANCEL_CURRENT);
NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
Resources res = context.getResources();
NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
long[] pattern = {0,300};
builder.setContentIntent(contentIntent)
.setSmallIcon(R.drawable.ic_launcher)
.setLargeIcon(BitmapFactory.decodeResource(res, R.drawable.ic_launcher))
.setTicker(res.getString(R.string.app_name))
.setWhen(System.currentTimeMillis())
.setAutoCancel(true)
.setVibrate(pattern)
.setContentTitle(res.getString(R.string.notification_title))
.setContentText(res.getString(R.string.notification_text));
Notification n = builder.build();
nm.notify(789, n);
}
I found the solution.. I turns out that the second argument to getBroadcast(Context context, int requestCode, Intent intent, int flags) makes the difference, even when the documentation says
requestCode Private request code for the sender (currently not used).
When a request id is used for each event, the alarm is updated and alarms are created for each event.
The reason is that with two different request codes, the filterEquals(Intent) will be false. Documentation of AlarmManager set(...) says:
If the time occurs in the past, the alarm will be triggered
immediately. If there is already an alarm for this Intent scheduled
(with the equality of two intents being defined by
filterEquals(Intent)), then it will be removed and replaced by this
one.
I also changed PendingIntent.FLAG_ONE_SHOT to PendingIndent.FLAG_CANCEL_CURRENT.

Categories

Resources