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" />
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 tried to use the setRepeating of AlarmManager, and then I read that the method isn't working anymore in API 26+, so the another solution was to schedule each alarm when the previous is finish. How can I do that?
MainActivity.java
public class MainActivity extends AppCompatActivity {
calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, Integer.parseInt(hour.getText().toString()));
calendar.set(Calendar.MINUTE, Integer.parseInt(minute.getText().toString()));
calendar.set(Calendar.SECOND, 00);
Intent intent = new Intent(getApplicationContext(), Notification_receiver.class);
pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 1, intent, PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
}
Notification_reciever.java
public class Notification_receiver extends BroadcastReceiver {
NotificationManager notificationManager = (NotificationManager) context.getSystemService(context.NOTIFICATION_SERVICE);
Intent repeating_intent = new Intent(context, MainActivity.class);
repeating_intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(context, time, repeating_intent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
.setContentIntent(pendingIntent)
.setChannelId(CHANNEL_ID)
.setSmallIcon(R.drawable.ic_baseline_notifications_active_24)
.setContentTitle("Notification Title")
.setContentText("Notification Text")
.setAutoCancel(true);
notificationManager.notify(time, builder.build());
}
How can i create another alarm manager when the previous is finish?
You will need to schedule your next alarm, at the end of BroadcastReceiver
public class AlarmBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
...
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, nextAlarmTimeInMillis(), pendingIntent);
Please note that, due to different battery saving mechanism implemented by different OEMs, AlarmManager is not guarantee to work all the time. Please refer to https://issuetracker.google.com/issues/122098785
In short, AlarmManager is the current best available mechanism, for timed notification to work, even without Internet connection. But, it is not gurantee to work all the time.
Here is example to make alarm every 2 minutes (tested on API 30)
move code to set alarm from MainActivity in own class
public class AlarmExecutor {
public static void makeAlarm(Context context, int minute) {
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.add(Calendar.MINUTE, minute);
Intent intent = new Intent(context, Notification_receiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
Log.d("Testing", "make alarm at " + calendar.getTime().toString());
}
}
now you can add in
Notification_receiver.java after notificationManager.notify(time, builder.build());
MainActivity
following line
// make alarm in 2 minutes
AlarmExecutor.makeAlarm(context, 2);
that will make an alarm every 2 minutes.
And don't forget to register the receiver in Manifest
<application >
<receiver android:name=".yourReceiver" />
</application>
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?
I'm new to this, so I'm a bit lost.
I have built a notification and passed it to the alarm manager as a pendingIntent, however instead of waiting the interval to trigger the alarm and showing the notification, the notification is instantly shown.
What have I done wrong, that isn't allowing the alarm to be set properly?
public class NotificationController{
Context context;
public void createNotification(Context context){
this.context = context;
Notification notification = getNotification();
//creates notification
Intent intent = new Intent(context, NotificationReceiver.class);
intent.putExtra(NotificationReceiver.NOTIFICATION_ID, 1);
intent.putExtra(NotificationReceiver.NOTIFICATION, notification);
PendingIntent pIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
//schedules notification to be fired.
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, 10000 , pIntent);
}
private Notification getNotification(){
Intent intent = new Intent(context, MainActivity.class);
PendingIntent pIntent = PendingIntent.getActivity(context, 0, intent, 0);
Notification.Builder builder = new Notification.Builder(context)
.setContentTitle("Reminder")
.setContentText("Car service due in 2 weeks")
.setSmallIcon(R.drawable.ic_launcher)
.setContentIntent(pIntent);
return builder.build();
}
}
my receiver
public class NotificationReceiver extends BroadcastReceiver {
public static String NOTIFICATION_ID = "notification-id";
public static String NOTIFICATION = "notification";
public void onReceive(Context context, Intent intent) {
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = intent.getParcelableExtra(NOTIFICATION);
int id = intent.getIntExtra(NOTIFICATION_ID, 0);
notification.flags |= Notification.FLAG_AUTO_CANCEL;
notificationManager.notify(id, notification);
}
}
I have also registered with <receiver android:name=".NotificationReceiver" > in the AndroidManifest.
In this line
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, 10000 , pIntent);
You specify that the alarm has to fire at 10 seconds after the device has been booted (which is in the past, so the alarm fires immediately). If you would want it 10 seconds after you set the alarm, you use the number of milliseconds since the device has been booted PLUS 10 seconds:
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, System.currentTimeMillis() + 10000 , pIntent);
Try this:
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, System.currentTimeMillis()+10000 , pIntent);
For me old methods are killing after few hours . Please see my code that i am using for different OS versions. May be helpful.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
AlarmManager.AlarmClockInfo alarmClockInfo = new AlarmManager.AlarmClockInfo(alarmTime, pendingIntent);
alarmManager.setAlarmClock(alarmClockInfo, pendingIntent);
}
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
alarmManager.setExact(AlarmManager.RTC_WAKEUP, alarmTime, pendingIntent);
}
else {
alarmManager.set(AlarmManager.RTC_WAKEUP, alarmTime, pendingIntent);
}
Thanks
Arshad
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
and
Intent notifyIntent = new Intent(this, MyReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, NotificationKeys.NOTIFICATION_ID, notifyIntent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Calendar alarmStartTime = Calendar.getInstance();
alarmStartTime.set(Calendar.SECOND, 5);
alarmManager.setExact(AlarmManager.RTC_WAKEUP, alarmStartTime.getTimeInMillis(), pendingIntent);
If you want to set is at a excat time, you should use setExact. Unfortunalety there is no setExactRepating so you have to create this yourself. Schedule a new alarm after one executes or something like that
for more refer https://stackoverflow.com/a/30812993/8370216
I am trying to implement an alarm that would display a notification everyday at the same hour of the day.
Here is the function I'm calling in my activity:
private void restartNotify() {
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
// Intent for our BroadcastReceiver
Intent intent = new Intent(this, AlarmReceiver.class);
// PendingIntent for AlarmManager
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT );
// In case we have already set up AlarmManager, we cancel.
am.cancel(pendingIntent);
am.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()+10000, pendingIntent);
}
And here is my broadcast receiver class
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
NotificationManager nm = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = new Notification(R.drawable.icon_notif, context.getString(R.string.NotificationLaunchMssg), System.currentTimeMillis());
// This is intent we want to launch when user clicks on the notification.
Intent intentTL = new Intent(context, MyClass.class);
notification.setLatestEventInfo(context, context.getString(R.string.NotificationTitle), context.getString(R.string.NotificationBody),
PendingIntent.getActivity(context, 0, intentTL, PendingIntent.FLAG_CANCEL_CURRENT));
nm.notify(1, notification);
//Here we set next notification, in day interval
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
am.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()+10000, pendingIntent);
}
}
As you can see in this code I am using a test value (+10000 milliseconds) because I am simply trying to trigger the alarm 10 seconds after my app has started. But it doesn't work, nothing is displayed.
I don't know if the alarm has a problem, or the notification, nothing is happening.
Do you have any idea why?
Thanks for your help
EDIT: after adding some test code in AlarmReceiver method, it turns out this code is never run. So I probably don't call it properly, what is wrong?
Do not use this approach try setInexactRepeating(...) or setRepeating(...) instead. Why are u giving extra work to the BroadcastReceiver for setting alarm every time it receives the intent.
here is a little code:
alarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
0, 10000, pendingIntent);
// The pending intent will the same as yours. 10000 is the
// interval for between consecutive alarms
as azertiti mentioned in comments " By the time it's registered that time will already be in the past." so use 0 or System.currentTimeMillis().