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
Related
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 have a TimePicker and a Button and I want to set an alarm when the user clicks on the Button at the time specified.
It gets the hour well when I click on the button but the alarm is being fired sometimes at the specified time, but not always. It is fired at the specified time less times than it does not fired. Most of the times the BroadcastReceiver does not fire at the specified time, it fires with a delay.
This is the code that I have right now:
On Alarm class (code refered to the BroadcastReceiver)
AlarmManager alarm = (AlarmManager) getSystemService(ALARM_SERVICE);
Intent intent = new Intent(getApplicationContext(), AlarmReceiver.class);
PendingIntent alarmIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, intent, 0);
Calendar cal= Calendar.getInstance();
cal.set(Calendar.MONTH,cal.get(Calendar.MONTH));
cal.set(Calendar.YEAR,cal.get(Calendar.YEAR));
cal.set(Calendar.DAY_OF_MONTH,cal.get(Calendar.DATE));
cal.set(Calendar.HOUR_OF_DAY,hour);
cal.set(Calendar.MINUTE,minutes);
alarm.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), 1000 * 60 * 5, alarmIntent);
where hour and minutes are the hour and minutes retrieved from the TimePicker.
On AlarmReceiver class
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.d("prove", "We enter on BroadcastReceiver");
}
}
On Manifest.xml
<receiver
android:name=".AlarmReceiver"
android:enabled="true" >
</receiver>
For example, I have put a log to see what hour I was retrieving from TimePicker before show the log of BroadcastReceiver. I clicked it at 16:48 (on the TimePicker) and this is the result:
12-06 16:47:02.951 7980-7980/com.project.user.project D/prove: hour: 16:48
12-06 16:50:23.727 7980-7980/com.project.user.project D/prove: We enter on BroadcastReceiver
12-06 17:00:01.070 7980-7980/com.project.user.project D/prove: We enter on BroadcastReceiver
As you can see, the BroadcastReceiver has been fired two times at 16:50 and 17:00 when I suppose that they should fire at 16:48 and 16:53 because I have set that it will be a delay of 5 minutes between them, not 10 minutes as in this case.
So, what can I do to fire the alarm at the exact time and not fire it with a delay? Am I missing some configuration?
Thanks in advance!
As mentioned in the documentation, setRepeating is inexact.
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, to fire the alarm at the exact time as of API 19, use setExact, and inside each alarm set the next alarm.
Schedule an alarm to be delivered precisely at the stated time.
Use setInexactRepeating
alarm.setInexactRepeating(AlarmManager.RTC_WAKEUP,System.currentTimeMillis(), 1000 * 60 * 5, alarmIntent);
And you can check my code what I did in my app.I worked perfect.
pendingIntent = PendingIntent.getBroadcast(this, _id, myIntent, PendingIntent.FLAG_CANCEL_CURRENT);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, timeToAlarm, AlarmManager.INTERVAL_DAY, pendingIntent);
May it help..
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
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.
In my code the Interval ( third parameter) on setRepeating() method seems not firing every 5 sec .
It keeps increasing in time, it's like the first one or 2 are mostly in time but the others fires like after 40+secs
So what's wrong here?
public class MainActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent i = new Intent(this, MainActivity2Activity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pi = PendingIntent.getActivity(this, 0, i, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE );
am.setRepeating(RTC_WAKEUP,System.currentTimeMillis(),1000*5,pi);
}
}
Take a look here: http://developer.android.com/reference/android/app/AlarmManager.html#setRepeating(int, long, long, android.app.PendingIntent)
As you're firing alarm every 5 seconds:
Note: for timing operations (ticks, timeouts, etc) it is easier and much more efficient to use Handler.
Your code is ok. Explanation of a delay you're experiencing may be:
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.
From what I understand from your code you are trying to run MainActivity2Activity.class 5 seconds after the creation of MainActivity.class.
I would advice you to use FLAG_UPDATE_CURRENT instead of FLAG_CANCEL_CURRENT in your pending intent.
The FLAG_CANCEL_CURRENT would retain your first ever pending intent and won't update or create a new one until and unless you cancel the original pending intent first.
Using FLAG_UPDATE_CURRENT will ensure that the pending intent is updated every time MainActivity.class is executed, so that pending intent will be fired exactly after 5 seconds the MainActivity.class is created.
Hope this helps.
Basically you wrote PendingIntent.FLAG_CANCEL_CURRENT instead of PendingIntent.FLAG_ONE_SHOT.
Code for Set Alarm by Alarm Manager
AlarmManager alarmManager = (AlarmManager) getBaseContext().getSystemService(ALARM_SERVICE);
Intent i1 = new Intent(this, ReceiveAlarmActivity.class);
i1.putExtra("Key", "Value");
PendingIntent operation = PendingIntent.getActivity(getBaseContext(), 0, i1, PendingIntent.FLAG_ONE_SHOT);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, Your_Date.getTime(), 5000 operation);
You have to pass Your Date.
Done