I am using an alarm manager to trigger an intent service every 40 seconds. The below code is how I am triggering the alarm and starting the service. I know that the alarm is not always triggered after 40 seconds exactly and may vary.
But I got a case where the alarm varied a lot and stayed constantly triggering EXACTLY every 5 minutes.
starting the alarm:
Intent alarmIntent = new Intent(context, AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, alarmIntent, 0);
AlarmManager manager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
long interval = 40000;
manager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), interval, pendingIntent);
alarm receiver:
#Override
public void onReceive(Context arg0, Intent arg1)
{
globalVariables.DebugLogging("IsSignedIn: "+GlobalVariables.IsSignedIn+" -DownloadServiceCanStart:- "+GlobalVariables.DownloadServiceCanStart);
if(GlobalVariables.IsSignedIn)
{
if (GlobalVariables.DownloadServiceCanStart)
{
GlobalVariables.DownloadServiceCanStart=false;
Intent intent = new Intent(arg0, DownloadService.class);
context.startService(intent);
}
}
}
The AlarmManager is not very precise.
As the official documentation states:
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.
There is also a minimum interval of 60 seconds. So your 40 second interval would be expanded to 60 seconds.
If you want to run something every 40 seconds exactly, you could investigate this answer:
https://stackoverflow.com/a/9539579/503508
Related
Muslims prayer times are 5 time a day , so i want my app to always check time , and when the current time matches with one from the 5 time, the App trigger an Action like play a media file , or send A notification to the userŅ
Use AlarmManager
AlarmManager mAlarmManger = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
//Create pending intent & register it to your alarm notifier class
Intent intent = new Intent(this, AlarmReceiver_maandag_1e.class);
intent.putExtra("uur", "1e"); // if you want
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
//set timer you want alarm to work (here I have set it to 9.00)
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 9);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
//set that timer as a RTC Wakeup to alarm manager object
mAlarmManger.setExact(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
Thanks to zipo13 for the correction. As GoogleDeveloper say
Note: Beginning with API 19 (Build.VERSION_CODES.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.
I have been trying to schedule an Android service to run repeatedly using the AlarmManager class, but the service stops being called after a couple of days. Originally I had been using the below code to try and achieve this:
Intent alarmIntent = new Intent(currentActivity.getApplicationContext(), AlarmReceiver.class);
PendingIntent pendingAlarmIntent = PendingIntent.getBroadcast(currentActivity.getApplicationContext(),
AppManager.ALARM_PENDING_INTENT_REQUEST_CODE,
alarmIntent,
PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager alarmManager = (AlarmManager)currentActivity.getApplicationContext().getSystemService(Context.ALARM_SERVICE);
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP,
System.currentTimeMillis(),
interval,
pendingAlarmIntent);
with the receiver:
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context _context, Intent _intent){
Intent serviceIntent = new Intent(_context.getApplicationContext(), PostLocationService.class);
_context.getApplicationContext().startService(serviceIntent);
}
}
This worked for a few days and then suddenly stopped. So I changed the code to initially broadcast to the receiver once and then re broadcast to the receiver each time the Service is run. I did this with the following code:
Intent alarmIntent = new Intent(currentActivity.getApplicationContext(), AlarmReceiver.class);
PendingIntent pendingAlarmIntent = PendingIntent.getBroadcast(currentActivity.getApplicationContext(),
AppManager.ALARM_PENDING_INTENT_REQUEST_CODE,
alarmIntent,
PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager alarmManager = (AlarmManager)currentActivity.getApplicationContext().getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP,
interval,
pendingAlarmIntent);
Unfortunately this has the same result; the Service stops being executed after a couple of days.
I have also registered a receiver for when the device boots to re initiate the AlarmManager call which is the same code as above.
Am I missing something? Is there a better approach than either of the above methods for this type of constant repetitive execution?
According to the developer site:
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
Blockquote
see more
hopes it will help
I want to call a BroadcastReceiver after specific interval of time. BroadcastReceiver is calling but it is not calling exactly after 10 seconds sometimes it call is 20 sec sometimes more than 20 seconds. I want to call BroadcastReceiver exactly after 10 seconds
This is the code of MainActivity
Intent myIntent = new Intent(MainActivity.this, SampleReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 0, myIntent,0);
AlarmManager alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, wakeupTime,1000 * 10, pendingIntent);
This is code of broadcastreceiver
public class SampleReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.e("Brodcast","receiver");
}
}
This is my log file
09-05 14:48:21.444 18222-18222/com.loconav.partners.tracker E/Brodcast: receiver
09-05 14:49:21.509 18222-18222/com.loconav.partners.tracker E/Brodcast: receiver
09-05 14:50:31.578 18222-18222/com.loconav.partners.tracker E/Brodcast: receiver
09-05 14:51:21.618 18222-18222/com.loconav.partners.tracker E/Brodcast: receiver
From the documentation of AlarmManager:
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.
Exact repeating is not possible currently with a single set of an alarm on API level 19+.
If you would like your repeating alarm to fire exactly when you want it, then you should use setExact() (or setExactAndAllowWhileIdle() according to your needs) and reschedule it every time it fires.
I don't know whats in wakeupTime.
The code works for me as
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(),1000*10,pendingIntent);
First, use ELAPSED_REALTIME_WAKEUP type, because you don't need fire alarm at a specific time of day. When you use rtc time, it can be updated by the system - when it syncs with time server, and your alarm could be never fire up at all.
Second, do not use BroadcastReceivers defined as subclasses of Activity - they should be set up in AndroidManifest.xml, because if your activity is destroyed - you will never receive your Intent.
I thinking you have to provide unique request code to get broadcast method.
Intent myIntent = new Intent(MainActivity.this, SampleReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(MainActivity.this, uniqueRequestCode, myIntent,0);
AlarmManager alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, wakeupTime,1000 * 10, pendingIntent);
uniqueRequestCode could be the System.currentTimeInMilliSecond
I need my alarm to fire every 30 seconds - exactly as possible (+/-3 seconds). So I read this (official Android guide) and implemented this:
AlarmManager alarm = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, MyService.class);
PendingIntent pendingIntent = PendingIntent.getService(context, 0, intent, 0);
alarm.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 30000, pendingIntent);
Result: The Alarm fires +/- every 50 seconds, which is not so much accurate if I gave interval of 30 seconds.
Where is the problem and what's going on here? In the documentation they say things about be careful with exact timers since cpu & battery consuming etc. but nevertheless still there is an option for exact if I want, and this is what I thought I implemented.
try this:
alarm.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + (2 * 1000), (30 * 1000), pendingIntent);
change delay 2 or up seconds for start alarm on firt time.
I want to show toast at a specific time using AlarmManger but my toast is not shown at given time? Help me.
My code is as follows:
private void startAlarm() {
Calendar cal=Calendar.getInstance();
cal.set(Calendar.DAY_OF_MONTH,9);
cal.set(Calendar.MONTH,7);
cal.set(Calendar.YEAR,2015);
cal.set(Calendar.HOUR_OF_DAY,2);
cal.set(Calendar.MINUTE,55);
cal.set(Calendar.AM_PM,Calendar.PM);
Intent intent = new Intent(this, WelcomActivity.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this.getApplicationContext(), 0, intent, 0);
AlarmManager alarmManager = (AlarmManager)getApplicationContext().getSystemService(ALARM_SERVICE);
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(),
AlarmManager.INTERVAL_DAY, pendingIntent);
Toast.makeText(this, "Alarm worked.", Toast.LENGTH_LONG).show();
}
The documentation for setInexactRepeating states:
Your alarm's first trigger will not be before the requested time, but it might not occur for almost a full interval after that time.
[edit thanks to ci_]
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.
So you need to use one-time exact alarms and reschedule as described in the documentation.