I have simply functional for start service and repeat he:
mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
PendingIntent pIntent = PendingIntent.getService(mContext,
SendStatusService.SEND_STATUS_SERVICE_CODE,
mIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
mAlarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + 2000,
mIntervalInMs,
pIntent);
I understand the documentation: alarm manager regardless of device state (sleep or not) start service through 2000 ms and repeat with interval mIntervalInMs.
But service start working after 30-50 sec after running this code. What i make wrong or no understand the documentation?
setRepeating() is "inexact" with a targetSdkVersion of 19 or higher when running on an API Level 19+ Android device. Hence, your results are not surprising. The events will occur somewhere around the desired time (until Android 6.0's Doze mode kicks in), but they will not occur exactly at the desired time.
Related
I have an app that uses an AlarmManager to schedule a service to repeat at a set frequency, say every hour.
From Android 6, devices will drop into Doze mode, this mode ignores wakelock and Alarms, potentially running them in the maintenance window. I would prefer that the Alarm executes when it is scheduled even if the device is in low-power idle modes.
I understand i can use setExactAndAllowWhileIdle to execute the alarm in Doze but this will excute only once. I cannot see any method that has this functionality but will repeat at a set frequency.
for example i use the code below to fire an alarm every hour. Is there a way to use setExactAndAllowWhileIdle so it repeats?
// get a Calendar object with current time
Calendar cal2 = Calendar.getInstance();
// add 5 minutes to the calendar object
cal2.add(Calendar.MINUTE, 1);
Intent intentTracking = new Intent(getApplicationContext(), TrackingAlarmReceiver.class);
// In reality, you would want to have a static variable for the request code instead of 192837
PendingIntent sender3 = PendingIntent.getBroadcast(getApplicationContext(), 192839, intentTracking, PendingIntent.FLAG_UPDATE_CURRENT);
// Get the AlarmManager service
AlarmManager am3 = (AlarmManager) getSystemService(ALARM_SERVICE);
//am.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), sender);
am3.setRepeating(AlarmManager.RTC_WAKEUP, cal2.getTimeInMillis(), ((Integer.parseInt(carerTrackingInteval)) * 60000 ), sender3);
ADM is spot-on.
As part of the work in TrackingAlarmReceiver, you call setExactAndAllowWhileIdle() to schedule the next bit of work.
Bear in mind that the minimum granularity of such events is ~10 minutes IIRC, and that you may not have network access even though you get control.
Though this question is repeated over and over here on SO, but non of the solutions are working, in the code below it should fire for the first time after 10 seconds from launching my activity, but it launch immediately. And I'm using FLAG_UPDATE_CURRENT so there's no past time to fire immediately as I'm not setting it at specific hour/minute/sec. Could you please bring my attention to what I'm missing.
I'm testing on Android 5.0 Targeting API 4.0+
compileSdkVersion 23
minSdkVersion 16
targetSdkVersion 23
Intent myIntent = new Intent(this, check.class);
PendingIntent pi = PendingIntent.getBroadcast(this, 0, myIntent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
am.setRepeating(AlarmManager.RTC, 10000, (AlarmManager.INTERVAL_DAY / 8), pi);
And this is my check.class in AndroidManifest.xml
<receiver
android:name=".Check"
android:exported="false" />
10000 on the real time clock is always going to be in the past, so your alarm fires immediately. You want System.currentTimeMillis() + 10000 as the second argument in the setRepeating() call.
I would point out that setRepeating() is inexact as of KitKat, so the actual time the alarm fires may be off. If it matters, use the setExact() method instead, setting the alarm again for the desired interval each time it fires.
I'm new in android. I struggle with my application approximately 3 weeks. I need sent and receive packets in normal mode and sleep mode. My app must exchange data a 5 seconds. I tried using alarmmanager but on android 5 it's not works. On android 5 an interval changes it on 60 seconds. Such a solution makes the battery wears out quickly. When I use normal asynctask, not IntentService, then it works only when screen is ON and app is visible. When app is hidden or I click power OFF then exchange data stops working. What is the best solutions?
Even RTC_WAKEUP doesn't help most of the times.
Solution that worked for my app when device in deep sleep mode:
Use WakefulBroadcastReceiver combined with AlarmManager.
Service is started by startWakefulService() and when it is finished, it releases the wake lock by calling completeWakefulIntent(intent). So the device will be allowed to go back to sleep.
I'm not adding any code. Search for examples on how to use WakefulBroadcastReceiver with AlarmManager. Even WakefulBroadcastReceiver doc has some template code.
Also reduce the frequency of alarm so you can avoid draining so much battery.
You can use the AlarmManager class to wake up the device at a particular time, then fire off an operation at whatever interval you'd like. Code from the docs found here:
private AlarmManager alarmMgr;
private PendingIntent alarmIntent;
...
alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, AlarmReceiver.class);
alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
// Set the alarm to start at 8:30 a.m.
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 8);
calendar.set(Calendar.MINUTE, 30);
// setRepeating() lets you specify a precise custom interval--in this case,
// 20 minutes.
alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
1000 * 60 * 20, alarmIntent);
Notice the last line of this block. You can use the method setRepeating() to set whatever interval you'd like.
I am using an AlarmManager in a Service to be triggered every minute.
PendingIntent pendingIntent = PendingIntent.getService(getApplicationContext(), 0,
getUpdateServiceIntent(mContext), PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
// Cancel any pending Intent
am.cancel(pendingIntent);
// Set a new one
am.set(AlarmManager.RTC_WAKEUP, 60000, pendingIntent);
On the Samsung S5 Neo :
When the screen is active, it is working as expected.
When the screen is off, it is triggered every 5 minutes (instead of one).
I try this exact same code on S5 Mini (with Android 4.4), Nexus 5 5.1 and Nexus 5 6.0, this code is working fine.
targetSdkVersion is 19.
Any idea how to keep the AlarmManager working correctly when screen is off ?
The delay is still 5 minutes, even if I ask for 30 seconds.
EDIT :
I also tried the 'setExact' method, but it didn't change anything. Still have a 5 minutes interval between each alarm.
You should probably use
AlarmManager#setExact(int type, long triggerAtMillis, PendingIntent operation)
instead of
AlarmManager#set(int type, long triggerAtMillis, PendingIntent operation))
Take a look
From google :
AlarmManager#set(int type, long triggerAtMillis, PendingIntent operation))
Note: Beginning in API 19, the trigger time passed to this method is treated as inexact: the alarm will not be delivered before this time, but may be deferred and delivered some time later. The OS will use this policy in order to "batch" alarms together across the entire system, minimizing the number of times the device needs to "wake up" and minimizing battery use. In general, alarms scheduled in the near future will not be deferred as long as alarms scheduled far in the future.
Edit :
What i am using for an alarm application :
Manifest :
<uses-permission android:name="android.permission.WAKE_LOCK"/>
Java Code :
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
AlarmManager.AlarmClockInfo alarmClockInfo = new AlarmManager.AlarmClockInfo(nextAlarm.getTimeInMillis(), pendingIntent);
alarmManager.setAlarmClock(alarmClockInfo, pendingIntent);
}else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
alarmManager.setExact(android.app.AlarmManager.RTC_WAKEUP, nextAlarm.getTimeInMillis(), pendingIntent);
}else {
alarmManager.set(android.app.AlarmManager.RTC_WAKEUP, nextAlarm.getTimeInMillis(), pendingIntent);
}
I'm attempting to use AlarmManager to schedule a delayed check in my app. (Specifically, N minutes after a user approaches a location, I want to check whether they're still there, and if so send them a notification.)
I've implemented this by checking to see whether they've entered the region in my location update receiver and, if they have, scheduling like so:
Intent geofenceIntent = new Intent(context, GeofenceReceiver.class)
// ...intent contents not important...
PendingIntent pi = PendingIntent.getBroadcast(context, 0, geofenceIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Calendar c = Calendar.getInstance();
c.add(Calendar.SECOND, getGeofenceDelaySeconds());
AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, c.getTimeInMillis(), pi);
Log.v("Scheduling notification check for "+c.getTime());
When the battery level is high (say, 50%), everything works like a charm. But when it's low (say, 10%), I get location updates, they schedule the alarm seemingly-successfully, but that alarm never actually triggers!
What gives? Does Android stop sending certain types of updates when it's trying to conserve power? How can I work around this (short of actually keeping my app active for the duration of the delay, which causes obvious issues with battery life)?
It turns out that this is related to the use of the real-time clock.
Although I could not find the documentation it quotes (it's not in AlarmManager), this StackOverflow answer suggests that AlarmManager.RTC_WAKEUP alarms do not trigger if the phone is in power-saving mode. AlarmManager.ELAPSED_REALTIME_WAKEUP alarms do not seem to suffer this problem, so I was able to fix the issue by switching to:
Intent geofenceIntent = new Intent(context, GeofenceReceiver.class)
// ...intent contents not important...
PendingIntent pi = PendingIntent.getBroadcast(context, 0, geofenceIntent, PendingIntent.FLAG_UPDATE_CURRENT);
long millis = SystemClock.elapsedRealtime() + 1000 * getGeofenceDelaySeconds();
AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, millis, pi);