I'm using the AlarmManager to fire a notification daily in specific time which is selected via time picker. The notification fired correctly in the same day but doesn't repeat correctly every day!!!
This is the method for setting the notification using setRepeating():
public void witer_reminder(View view)
{
am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(this, Witer_Notification.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0,
intent, PendingIntent.FLAG_CANCEL_CURRENT);
Calendar cal = Calendar.getInstance();
Calendar calSet = (Calendar) cal.clone();
calSet.set(Calendar.HOUR_OF_DAY, picker.getCurrentHour());
calSet.set(Calendar.MINUTE, picker.getCurrentMinute());
calSet.set(Calendar.SECOND, 0);
calSet.set(Calendar.MILLISECOND, 0);
if(calSet.compareTo(cal) <= 0)
{
// Today Set time passed, count to tomorrow
calSet.add(Calendar.DATE, 1);
}
am.setRepeating(AlarmManager.RTC_WAKEUP, calSet.getTimeInMillis(),
24 * 60 * 60 * 1000, pendingIntent);
}
and this is the BroadcastReciver class:
public class Witer_Notification extends BroadcastReceiver
{
NotificationManager nm;
#Override
public void onReceive(Context context, Intent intent)
{
PendingIntent contentIntent = PendingIntent.getActivity(context, 0,
new Intent(context, MainActivity.class), 0);
PendingIntent actiontIntent = PendingIntent.getActivity(context, 0,
new Intent(context, Suggestion.class), 0);
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("")
.setStyle(new NotificationCompat.BigTextStyle().bigText(""));
mBuilder.setContentIntent(contentIntent);
mBuilder.setDefaults(Notification.DEFAULT_SOUND);
// mBuilder.setStyle(new NotificationCompat.InboxStyle());
NotificationManager mNotificationManager = (NotificationManager)
context.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(1, mBuilder.build());
}
}
BTW, the application target is SDK 19.
I found that the setExact() replacing to set()
Correct.
it's not applicable for intervalAtMilis as a parameter
Not directly. But, when you get control in your BroadcastReceiver from the setExact() event, call setExact() again to schedule the next event.
I didn't find anything for setRepeating()
There is no simple solution, because Google is trying to point out to you that this is bad for the battery. Using setExact() as described above is your only option for exact repeating.
Related
I have a problem with notifications in my app. I want to set multiple notifications for different hours of the day. For example, let's take 8, 12 and 23 o'clock. But only the one at 23 o'clock triggers every day. What's wrong with my code and will it work even if the app is killed?
Here's the code that sets alarms in my activity
public void myAlarm(int hour, int minute) {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, hour);
calendar.set(Calendar.MINUTE, minute);
calendar.set(Calendar.SECOND, 0);
Intent intent = new Intent(getApplicationContext(), Reminder.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
if (alarmManager != null) {
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pendingIntent);
}
}
and this is what I wrote in onCreate
myAlarm(8, 0);
myAlarm(12, 0);
myAlarm(23, 0);
this is my receiver
public class Reminder extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent in = new Intent(context, MySecoundActivity.class);
in.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, in, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, "Reminder")
.setSmallIcon(R.drawable.bell)
.setContentTitle("Notification!")
.setContentText("Text of notification")
.setColor(0xfb3ff)
.setAutoCancel(true)
.setContentIntent(pendingIntent)
.setPriority(NotificationCompat.PRIORITY_HIGH);
NotificationManagerCompat notificationMngr = NotificationManagerCompat.from(context);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
CharSequence name = "Reminder";
String description = "reminder channel";
int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationChannel channel = new NotificationChannel("Reminder", name, importance);
channel.setDescription(description);
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.createNotificationChannel(channel);
}
notificationMngr.notify(200, builder.build());
}
Receiver is in android manifest
<receiver android:name=".Reminder"/>
This is the expected behavior since in your code, when you set the alarm, you have to give every PendingIntent unique requestCode which in your case remains the same, i.e., 0. So when you set another alarm with same requestCode, the last alarm gets updated to the new time instead of creating a new alarm. So only your last alarm works. So at the time of setting the alarm, in your PendingIntent.getBroadcast(), instead of the 0, you could use either the Random class to generate a random number every time or you could just use (int)System.currentTimeMillis() which would always be a different number.
I start to combine alarm manager and notification manager on android, and this is my code:
MainActivity.java
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setReminderAlarm();
}
public void setReminderAlarm() {
Intent intent = new Intent(MainActivity.this, ReminderReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(MainActivity.this, ReminderReceiver.NOTIF_ID, intent, 0);
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 6);
calendar.set(Calendar.MINUTE, 59);
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 86400000L, pendingIntent);
}
ReminderReceiver.java
public static int NOTIF_ID = 101;
#Override
public void onReceive(Context context, Intent intent) {
showAlarmNotification(context);
}
public void showAlarmNotification(Context context) {
Intent intentClick = new Intent(context, MainActivity.class);
PendingIntent pendingClick = PendingIntent.getActivity(context, 0, intentClick, 0);
NotificationManager notificationManagerCompat = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
Uri alarmSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.cinema)
.setContentTitle(title)
.setContentIntent(pendingClick)
.setContentText(message)
.setColor(ContextCompat.getColor(context, android.R.color.transparent))
.setVibrate(new long[]{1000, 1000, 1000, 1000, 1000})
.setSound(alarmSound)
.setAutoCancel(true);
notificationManagerCompat.notify(NOTIF_ID, builder.build());
}
Every time I run the application, the notification always appears even though I have set the time. How do I prevent that?
Thank you.
The issue is you are setting the time to current day. So if you are opening your app after 6:00, your alarm manager will immediately fire.
You need to check whether the time is over 6:00 for the current day, if yes you need to change the date to the next day:
public void setReminderAlarm() {
Intent intent = new Intent(MainActivity.this, ReminderReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(MainActivity.this, ReminderReceiver.NOTIF_ID, intent, 0);
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
int curHr = calendar.get(Calendar.HOUR_OF_DAY);
// Checking whether current hour is over 6
if (curHr >= 6)
{
// Since current hour is over 6, setting the date to the next day
calendar.add(Calendar.DATE, 1);
}
calendar.set(Calendar.HOUR_OF_DAY, 6);
calendar.set(Calendar.MINUTE, 59);
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 86400000L, pendingIntent);
}
I want the code to execute a notification once every day at 07 am. I created a debug apk and installed it to see how it performs and noticed, that it actually sends a notification at about 07 am, but if you click on the notification and get into the app and close it afterwars, it sends a notification again. Does someone see a mistake in the code?
this is the code in the MainActivity.java (the notification part):
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
intent_anmeldeActivity = new Intent(this, anmeldeActivity.class);
intent_WebViewActivity = new Intent(this, WebViewActivity.class);
prefs = getSharedPreferences("prefs", Context.MODE_PRIVATE);
prefsEditor = prefs.edit();
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 07);
calendar.set(Calendar.MINUTE, 00);
calendar.set(Calendar.SECOND, 00);
intent_notification = new Intent(this, NotificationClass.class);
Intent intent1 = new Intent(MainActivity.this, NotificationClass.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 0, intent1, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager am = (AlarmManager) MainActivity.this.getSystemService(MainActivity.this.ALARM_SERVICE);
am.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pendingIntent);
Also it sends notifications kind of randomly.
Thanks in advance!
EDIT:
public class NotificationClass extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
loadText loadText = new loadText();
loadText.startAsyncTask(context);
} }
In AsyncTask class loadText, the class NotificationBuilding is executed in onPostExecute:
public class NotificationBuilding {
Context mContext = null;
int ID = 1;
Uri alarmSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
long when = System.currentTimeMillis();
public void startNotificationBuilding(Context con, String title, String text) {
this.mContext = con;
NotificationManager notificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
Intent notificationIntent = new Intent(mContext, MainActivity.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0,
notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder mNotifyBuilder = (NotificationCompat.Builder) new NotificationCompat.Builder(
mContext)
.setSmallIcon(R.drawable.ic_stat_name)
.setColor(Color.argb(255, 234, 146, 21))
.setContentTitle(title)
.setContentText(text)
.setSound(alarmSound)
.setAutoCancel(true)
.setWhen(when)
.setContentIntent(pendingIntent)
.setVibrate(new long[]{1000, 1000, 1000, 1000, 1000})
.setLights(Color.argb(255, 234, 146, 21), 1000, 10000)
.setStyle(new NotificationCompat.BigTextStyle().bigText(text));
notificationManager.notify(ID, mNotifyBuilder.build());
ID++;
} }
// Set the alarm to start at approximately 7:00 a.m.
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 07);
// With setInexactRepeating(), you have to use one of the AlarmManager interval
// constants--in this case, AlarmManager.INTERVAL_DAY.
alarmMgr.**setInexactRepeating**(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
AlarmManager.INTERVAL_DAY, alarmIntent);
Decide how precise your alarm needs to be
As described above, choosing the alarm type is often the first step in creating an alarm. A further distinction is how precise you need your alarm to be. For most apps, setInexactRepeating() is the right choice. When you use this method, Android synchronizes multiple inexact repeating alarms and fires them at the same time. This reduces the drain on the battery.
For the rare app that has rigid time requirements—for example, the alarm needs to fire precisely at 8:30 a.m., and every hour on the hour thereafter—use setRepeating(). But you should avoid using exact alarms if possible.
With setInexactRepeating(), you can't specify a custom interval the way you can with setRepeating(). You have to use one of the interval constants, such as INTERVAL_FIFTEEN_MINUTES, INTERVAL_DAY, and so on. See AlarmManager for the complete list.
I'm looking to create a function for an Android app in which I get a notification every 25th day of the month indicating I have to do a certain task.
I've been able to display the notification using the following code :
public class NotificationPublisher extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
long[] pattern = {0, 300, 0};
PendingIntent pi = PendingIntent.getActivity(context, 01234, intent, 0);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.small_logo_ico)
.setContentTitle(context.getResources().getString(R.string.notification_title))
.setContentText(context.getResources().getString(R.string.notification_content))
.setVibrate(pattern)
.setAutoCancel(true);
mBuilder.setContentIntent(pi);
mBuilder.setDefaults(Notification.DEFAULT_SOUND);
mBuilder.setAutoCancel(true);
NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(01234, mBuilder.build());
}
}
Now this system only works when I have my app open and doesn't allow me to display this when the app is closed. I've searched around and came to this:
Android notification at specific date
After trying this out (the schedule part) I noticed that it doesn't work when I close the app, as I get an error about unregistering the Receiver, doing this (unregistering) results in the receiver being canceled, and the notification can not be showed.
code used for the schedule:
NotificationPublisher receiver = new NotificationPublisher();
this.receiver = receiver;
IntentFilter filter = new IntentFilter("ALARM_ACTION");
registerReceiver(receiver, filter);
Intent intent = new Intent("ALARM_ACTION");
intent.putExtra("param", "My scheduled action");
PendingIntent operation = PendingIntent.getBroadcast(this, 0, intent, 0);
// I choose 15s after the launch of my application
alarms.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()+15000, operation) ;
Is there anything I'm missing, or am I using the wrong methods to schedule a notification on a certain date? ( The current notification is set to be scheduled 15 seconds in the future, this is just for testing, I've got a function ready to display this at a certain date)
This is used to notify on middle of the month. Maybe You can get from below code.
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.DAY_OF_MONTH, 15);
calendar.set(Calendar.HOUR_OF_DAY, 12);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
if (calendar.getTimeInMillis() < System.currentTimeMillis()) {
calendar.add(Calendar.DAY_OF_YEAR, 30);
}
Intent myIntent = new Intent(getApplicationContext(), MyReceiver.class);
myIntent.putExtra("NOTI_MSG",getString(R.string.notification_sidas));
PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), NOTI_REQ_CODE_SIDAS, myIntent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
AlarmManager.INTERVAL_DAY * 30, pendingIntent);
}
I'm trying to broadcast after 20 seconds and receive the broadcast with an extended receiver ExtendedReceiver.
Here is my function that creates an alarm and sets the PendingIntent to go off after 20 seconds:
public void alert() {
GregorianCalendar cal = new GregorianCalendar();
cal.add(Calendar.SECOND, 20);
Intent i = new Intent(this, ExtendedReceiver.class);
int _uid = (int) System.currentTimeMillis();
PendingIntent pi = PendingIntent.getBroadcast(this, _uid, i, PendingIntent.FLAG_ONE_SHOT);
AlarmManager am = (AlarmManager)getSystemService(Activity.ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), pi);
Log.i("Title", "Alarm has been set");
}
Here is the ExtendedReceiver class:
public class ExtendedReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.i("Title", "Broadcast received");
}
}
I get my first log message: Alarm has been set but I don't get my second log message. I'm unsure where the problem lies (first day on Android)
If i may this is what i always do.
change your
PendingIntent pi = PendingIntent.getBroadcast(this, _uid, i, PendingIntent.FLAG_ONE_SHOT);
to
PendingIntent pi = PendingIntent.getBroadcast(this, _uid, new Intent(EXTENDED_RECEIVER_ACTION), PendingIntent.FLAG_ONE_SHOT);
and important: Register your ExtendedReceiver like this:
...
registerReceiver(new ExtendedReceiver() , new IntentFilter(EXTENDED_RECEIVER_ACTION));
PS: EXTENDED_RECEIVER_ACTION is a String and dont forget to unregister your receiver.
further docs here
hope it helps :)