I'm having a problem with the Android AlarmManager. I want to show a notification everyday at 00:01 AM. When i test the notification during the day at something like 11:30 AM the notification does show up. But when i test it at 00:01 AM nothing shows up.
I think this has something to do with my phone being asleep after a few hours of no activity at 00:01 AM, but I am not sure. Does anybody have a solution for this? Thanks in advance.
MainActivity:
Intent alarmIntent = new Intent(this, AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager manager = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 1);
Calendar now = Calendar.getInstance();
now.setTimeInMillis(System.currentTimeMillis());
if (calendar.before(now)) {
calendar.add(Calendar.DAY_OF_MONTH, 1);
manager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
AlarmManager.INTERVAL_DAY, pendingIntent);
} else {
manager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
AlarmManager.INTERVAL_DAY, pendingIntent);
}
AlarmReceiver:
private static int NOTIFICATION_ID;
private NotificationManager notificationManager;
private PendingIntent pendingIntent;
Intent mIntent;
#Override
public void onReceive(Context context, Intent intent) {
NOTIFICATION_ID = random.nextInt(9999 - 1000) + 1000;
notificationManager = (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE);
mIntent = new Intent(context, BirthdayActivity.class);
pendingIntent = PendingIntent.getActivity(context, NOTIFICATION_ID, mIntent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
builder.setContentTitle("Name");
builder.setContentIntent(pendingIntent);
notificationManager = (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE);
notificationManager.notify(NOTIFICATION_ID, builder.build());
}
Manifest:
<receiver android:name=".utils.AlarmReceiver" android:enabled="true">
</receiver>
<uses-permission android:name="com.android.alarm.permission.SET_ALARM"/>
I think everything is right with your code. You can check whether the alarm is set or not using this command on your android studio terminal.
adb shell dumpsys alarms >dump.txt
and then search for your package name in that file. This will confirm whether your alarm is set successfully or not.
Next you are using setRepeating which means system can adjust the delivery time. To deliver the alarm at the exact time use setExact
here is a excerpt from the official android documentation:
Note: as of API 19, all repeating alarms are inexact. If your application needs precise delivery times then it must use one-time exact alarms, rescheduling each time as described above.
From the api docs:
Note: as of API 19, all repeating alarms are inexact. If your
application needs precise delivery times then it must use one-time
exact alarms, rescheduling each time as described above. Legacy
applications whose targetSdkVersion is earlier than API 19 will
continue to have all of their alarms, including repeating alarms,
treated as exact.
https://developer.android.com/reference/android/app/AlarmManager.html#setRepeating(int, long, long, android.app.PendingIntent)
There are a few questions you should answer.
Does this really need to be exact?
If the user is sleeping can this wait until they wake up their phone?
Exact alarms are often discouraged as they disregard the state of the phone. For example, its not "nice" to the user to sync your app when they aren't even looking at their phone.
If you are connecting to a server and updating some data, I'd recommend a 'push' approach rather than a 'pull' approach.
They system only holds a wakelock while delivering the alarm notification to the AlarmReceiver. Unless there is some other reason for the device to stay awake, it is entirely possible that it will go back to sleep, before the Intent is delivered to the Activity.
Have a look at WakefulBroadcastReceiver
Related
I am trying to poll a device for long/lat every minute or so... I have been researching and found a few things. I was thinking of using:
PeriodicWorkRequestBuilder() - however, I have read that it can only execute every 15 minutes at a minimum...
What tech/design pattern are available to me, if I wanted to poll for data in a shorter period?
Are foreground services my only choice?
You can Use any Runnable but when app closed it will not working .
Foreground service is best choice but in android 9+, it will confuse the user
this is the link that show to you how use it:
Timer
BUT
I advice you to use an AlarmManager that work like work manager but it response better, you can Use Countdown timer for it, link below will help You to use it:
AlarmManager
Edited:
sample for open activity with alarm manager
Intent intent = new Intent(this, YOUR_MAIN_ACTIVITY.class);
intent.setAction(Intent.ACTION_MAIN);
intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
PendingIntent pendingIntent = PendingIntent.getActivity(this, ID,
intent, 0);
final long DELAY_IN_MILLIS = DELAY_IN_MILLI_SECONDS+
System.currentTimeMillis();
AlarmManager alarmManager = (AlarmManager)
getSystemService(Activity.ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC, DELAY_IN_MILLIS,pendingIntent);
and there is a full example for you:
Example
My requirement is set Notification for specific time like user birthday or holiday
I am using AlarmManager for scheduling notification using broadcast receiver
Code is working fine in 6.0 (even when app is killed,swiped from recent list) but not working on Android 8.1.0 (Mf : Oppo)
Readed This and This and many answers but not find any helpfull
any idea how to solve this issue
Here is my code
AlarmManager am = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);
//creating a new intent specifying the broadcast receiver\
Intent i = new Intent(this, HolidayBroadcast.class);
i.putExtra("eventName",islamicHoliday.getEventName());
i.putExtra("dateH", testTmp.getCalendar().getTimeInMillis());
i.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
//creating a pending intent using the intent
PendingIntent pi = PendingIntent.getBroadcast(this, new Random().nextInt(), i, PendingIntent.FLAG_UPDATE_CURRENT);
//setting alarm
if(Build.VERSION.SDK_INT>= Build.VERSION_CODES.M) {
am.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP,getTimeInMillis(), pi);
}
else
{
am.setExact(AlarmManager.RTC_WAKEUP, getTimeInMillis(), pi);
}
You can use workmanager as mentioned in link.It supports all api version and easy to use because it uses backward compatibility to API level 14
https://developer.android.com/topic/libraries/architecture/workmanager
https://medium.com/androiddevelopers/introducing-workmanager-2083bcfc4712
If your task is time critical, WorkManager API is not recommended as for your alarm manager not working properly, on Android 8 use
AlarmManager.setexactandallowwhileidle(), to set exact time and allow wakeup notification while app is killed.
I have set three repeating daily alarms on 12:00,16:00 and 20:00.
But I found that the first alarm would not activate on time, but instead go off 11:59:34, 12:00:12 and 12:00:56.
I don't know why this would happen, and I have read many documents, no one gives me an answer.
Please help me!
Here is my code:
//Set the Calendar
Calendar cal=Calendar.getInstance();
cal.setTimeInMillis(System.currentTimeMillis());
cal.set(Calendar.HOUR_OF_DAY, 12);
cal.set(Calendar.MINUTE, 00);
cal.set(Calendar.SECOND, 00);
//set PendingIntent
Intent alarmIntent = new Intent(context, AlarmReceiver.class);
alarmIntent.putExtra("alarmType", 3);
PendingIntent pendingIntentMoring = PendingIntent.getBroadcast(context, 51, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
PendingIntent pendingIntentAfternoon = PendingIntent.getBroadcast(context, 52, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
PendingIntent pendingIntentEvening = PendingIntent.getBroadcast(context, 53, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
//clear the alarm manager before set the new alarm
managerMorning.cancel(pendingIntentMoring);
managerAfternoon.cancel(pendingIntentAfternoon);
managerEvening.cancel(pendingIntentEvening);
//set new alarm
managerMorning.setRepeating(AlarmManager.RTC_WAKEUP, cal1.getTimeInMillis(),AlarmManager.INTERVAL_DAY, pendingIntentMoring);
managerAfternoon.setRepeating(AlarmManager.RTC_WAKEUP, cal2.getTimeInMillis(),AlarmManager.INTERVAL_DAY, pendingIntentAfternoon);
managerEvening.setRepeating(AlarmManager.RTC_WAKEUP, cal3.getTimeInMillis(),AlarmManager.INTERVAL_DAY, pendingIntentEvening);
//set Receiver
public void onReceive(Context context, Intent intent) {
Intent myMessageintent = new Intent(context, UpDateDiaryMessage.class);
myMessageintent.putExtra("alarmType", 3);
context.startService(myMessageintent);
}
I've tested it many times.
I can't get the alarm to activate 12:00:00, but I got two or three alarms around 12:00:00.
I don't know why it sometimes works and sometimes not.
As per the official docs:
Note: Beginning with API 19 (KITKAT) alarm delivery is inexact: the OS
will shift alarms in order to minimize wakeups and battery use. There
are new APIs to support applications which need strict delivery
guarantees; see setWindow(int, long, long, PendingIntent) and
setExact(int, long, PendingIntent). Applications whose
targetSdkVersion is earlier than API 19 will continue to see the
previous behavior in which all alarms are delivered exactly when
requested.
In a nutshell
for API < 19 you can use set() method. For these APIs this will set an exact alarm
for 19 <= API < 23 you should use setExact() to set exact alarms, and set() to set inexact alarms
for API = 23, Doze mode was also introduced, so in addition if you also want your alarm to go off even when the phone is in Doze mode, you should use setExactAndAllowWhileIdle() method instead.
I want to program an app that has two independent, repetitive alarms. There are two classes seem to be able do this: AlarmManager and AlarmClock. I've tested AlarmManager, but when Android restarts all alarms are cleared.
Which should I use?
Use BroadcastReceiver to handle Android OS boot broadcast and reschedule your alarms.
AlarmManager services allow you to schedule your application to be run at some point in the future. When an alarm goes off, the Intent that had been registered for it is broadcast by the system, automatically starting the target application if it is not already running.
You may find the SO post helpful Android AlarmManager
AlarmManager mgr=(AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent i=new Intent(context, OnAlarmReceiver.class);
PendingIntent pi=PendingIntent.getBroadcast(context, 0, i, 0);
mgr.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime(), PERIOD, pi);
Whereas AlarmClock provider contains an Intent action and extras that can be used to start an Activity to set a new alarm in an alarm clock application.
I have a GPS service whose work is to fetch the coordinate into a server. This service suppose to be run 24/7. but it is somehow killed in between.
This is happing only in android v 2.3. On android v2.2 it's running fine.
In this service , i am using "LocationManager" and it's method "requestLocationUpdates" which is creating a loop.This loop is responsible for fetching the coordinates. So my goal is to keep the loop running.
So what to do, to make by service run 24/7.
This server suppose to be run 24/7
You cannot do that. This is not possible in any real sense of the term, as you have discovered. It is also not a good design choice at all.
If you absolutely need it to be running all the time, you need to
acquire a PARTIAL_WAKE_LOCK via PowerManager. This will keep the CPU
on all the time, and your program running. Be prepared for a shocking
decline in battery life.
Instead use AlarmManager. You can schedule a PendingIntent via the AlarmManager thats starts the service at the relevant point in time to do it's work. When done, kill the service again.
Below is a sample code showing how the AlarmManager is used which will launch the intent to start YourService in 5 minutes from now:
// get a calendar with the current time
Calendar cal = Calendar.getInstance();
// add 5 minutes to the calendar object
cal.add(Calendar.MINUTE, 5);
Intent intent = new Intent(ctx, YourService.class);
PendingIntent pi = PendingIntent.getService(this, 123, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), pi);
Please use repeating Alarm Manager which start your service after a given time period
private void setAlarm() {
AlarmManager alarmManager = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(getApplicationContext(), LocationUpdateService.class);
intent.putExtra("locationSendingAlarm", true);
PendingIntent pendingIntent = PendingIntent.getService(this, AppConstants.PENDING_INTENET_LOCATION_SENDING_ALARM_ID, intent,0);
try {
alarmManager.cancel(pendingIntent);
} catch (Exception e) {
}
int timeForAlarm=5*1000*60; // 5 minutes
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,System.currentTimeMillis()+timeForAlarm, timeForAlarm,pendingIntent);
}