I am calling a background Service
at interval of 30 min to read the latitude/longitude of current location and sending it to server by POST API .
I am using setRepeating()
method of AlarmManager
class to schedule alarm every 30 minutes. But some times the alarm is getting missed and service is not called. To monitor if alarm gets called or not in every 30 min I have generated Log.txt file in the sdcard. For every time alarm called the entry for the current time will be written in the Log.txt file. But after comparing 4 to 5 devices Log.txt files I noticed that for some of devices alarm is not calling onCreate()
method of UserTrackingReceiver.java
(Background service) . Full code chunks mentioned below.
When app start registerUserTrackingReceiver()
method has been call which is below:
public static void registerUserTrackingReceiver(Context context) {
try {
Intent intent = new Intent(context, UserTrackingReceiver.class);
boolean alarmUp = (PendingIntent.getService(context, 1001, intent, PendingIntent.FLAG_NO_CREATE) == null);
if (alarmUp) {
Calendar calendar = Calendar.getInstance();
if (calendar.get(Calendar.MINUTE) > 0 && calendar.get(Calendar.MINUTE) <= 30) {
calendar.set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY));
calendar.set(Calendar.MINUTE, 30);
calendar.set(Calendar.SECOND, 0);
} else if (calendar.get(Calendar.MINUTE) > 30) {
if (calendar.get(Calendar.HOUR_OF_DAY) == 23) {
calendar.set(Calendar.HOUR_OF_DAY, 0);
} else {
calendar.set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY) + 1);
}
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
} else {
calendar.set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY));
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
}
PendingIntent sender = PendingIntent.getService(context, 1001, intent, 0);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(context.ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
AlarmManager.INTERVAL_HALF_HOUR, sender);
}
} catch (Exception e) {
e.printStackTrace();
}
}
UserTrackingReceiver.java is below:
public class UserTrackingReceiver extends Service
implements LocationListener,
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener {
@Override
public void onCreate() {
super.onCreate();
Calendar calendar = Calendar.getInstance();
Util.appendLog("Tracking Alarm Called on: " + calendar.get(Calendar.HOUR_OF_DAY) + " : " + calendar.get(Calendar.MINUTE) + " : " + calendar.get(Calendar.SECOND));
stopSelf();
}
}
In Util.java there is appendLog()
method which is below:
public static void appendLog(String text) {
String baseDir = Environment.getExternalStorageDirectory().getAbsolutePath();
File logFile = new File(baseDir + "/" + Constant.AppNameSuper + "/log.txt");
if (!logFile.exists()) {
try {
logFile.createNewFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
try {
//BufferedWriter for performance, true to set append to file flag
BufferedWriter buf = new BufferedWriter(new FileWriter(logFile, true));
buf.append(text);
buf.newLine();
buf.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
If alarm called every 30 min as per above code it should be written in Log.txt file in SDCARD. But the issue is it cannot write log file every 30 min that means alarm is missing. As per taking reading for two days I have noticed that alarm is not missing in day time as user continuously use their phone but it is missed in night when phone is not in use.
Out put log files with different devices are below:
Device A Log.txt
- Tracking Alarm Called on: 0 : 0 : 31(Start From 12:00 Night)
- Tracking Alarm Called on: 1 : 10 : 27
- Tracking Alarm Called on: 3 : 5 : 25
- Tracking Alarm Called on: 6 : 55 : 31
- Tracking Alarm Called on: 7 : 0 : 6
- Tracking Alarm Called on: 7 : 30 : 0
- Tracking Alarm Called on: 8 : 0 : 6
- Tracking Alarm Called on: 8 : 30 : 0
- Tracking Alarm Called on: 9 : 0 : 6
- Tracking Alarm Called on: 9 : 30 : 0
- Tracking Alarm Called on: 10 : 0 : 0
Device B Log.txt
- Tracking Alarm Called on: 0 : 0 : 27(Start From 12:00 Night)
- Tracking Alarm Called on: 0 : 30 : 1
- Tracking Alarm Called on: 1 : 0 : 1
- Tracking Alarm Called on: 1 : 30 : 2
- Tracking Alarm Called on: 2 : 0 : 1
- Tracking Alarm Called on: 2 : 30 : 1
- Tracking Alarm Called on: 3 : 0 : 1
- Tracking Alarm Called on: 3 : 30 : 1
- Tracking Alarm Called on: 4 : 0 : 1
- Tracking Alarm Called on: 4 : 30 : 29
- Tracking Alarm Called on: 5 : 0 : 1
- Tracking Alarm Called on: 5 : 30 : 2
- Tracking Alarm Called on: 6 : 0 : 30
- Tracking Alarm Called on: 6 : 30 : 1
- Tracking Alarm Called on: 7 : 0 : 1
- Tracking Alarm Called on: 7 : 30 : 1
- Tracking Alarm Called on: 8 : 0 : 1
- Tracking Alarm Called on: 8 : 30 : 1
- Tracking Alarm Called on: 9 : 0 : 32
- Tracking Alarm Called on: 9 : 30 : 1
Device C Log.txt
- Tracking Alarm Called on: 0 : 0 : 7(Start From 12:00 Night)
- Tracking Alarm Called on: 0 : 30 : 3
- Tracking Alarm Called on: 1 : 0 : 6
- Tracking Alarm Called on: 1 : 30 : 1
- Tracking Alarm Called on: 2 : 0 : 32
- Tracking Alarm Called on: 2 : 30 : 3
- Tracking Alarm Called on: 3 : 1 : 50
- Tracking Alarm Called on: 3 : 30 : 5
- Tracking Alarm Called on: 4 : 1 : 58
- Tracking Alarm Called on: 4 : 31 : 14
- Tracking Alarm Called on: 5 : 0 : 1
- Tracking Alarm Called on: 5 : 30 : 1
- Tracking Alarm Called on: 6 : 2 : 1
- Tracking Alarm Called on: 6 : 30 : 1
- Tracking Alarm Called on: 7 : 0 : 1
- Tracking Alarm Called on: 7 : 30 : 1
- Tracking Alarm Called on: 8 : 0 : 1
- Tracking Alarm Called on: 8 : 30 : 4
- Tracking Alarm Called on: 9 : 1 : 44
- Tracking Alarm Called on: 9 : 30 : 1
Device D Log.txt
- Tracking Alarm Called on: 0 : 1 : 25(Start From 12:00 Night)
- Tracking Alarm Called on: 0 : 30 : 0
- Tracking Alarm Called on: 1 : 31 : 41
- Tracking Alarm Called on: 2 : 39 : 52
- Tracking Alarm Called on: 3 : 0 : 25
- Tracking Alarm Called on: 3 : 30 : 58
- Tracking Alarm Called on: 4 : 0 : 25
- Tracking Alarm Called on: 4 : 30 : 56
- Tracking Alarm Called on: 5 : 30 : 51
- Tracking Alarm Called on: 7 : 18 : 55
- Tracking Alarm Called on: 7 : 30 : 0
- Tracking Alarm Called on: 8 : 0 : 25
- Tracking Alarm Called on: 8 : 30 : 43
- Tracking Alarm Called on: 9 : 0 : 3
- Tracking Alarm Called on: 9 : 30 : 25
- Tracking Alarm Called on: 10 : 0 : 25
- Tracking Alarm Called on: 10 : 30 : 4
- Tracking Alarm Called on: 11 : 1 : 52
- Tracking Alarm Called on: 11 : 30 : 27
- Tracking Alarm Called on: 12 : 1 : 6
The problem might be your
PendingIntent
calling aService
. The device can go back to sleep before yourService
finishes (or even starts) execution.I'd suggest you to use a
BroadcastReceiver
instead (since aWakeLock
is guaranteed duringonReceive()
).Acquire a
WakeLock
inonReceive()
, start yourService
from there and release theWakeLock
from theService
, when appropriate.To simplify this process you can use the
WakefulBroadcastReceiver
helper class:PendingIntent.getBroadcast()
instead ofPendingIntent.getService()
.IntentService
fromonReceive()
by callingWakefulBroadcastReceiver.startWakefulService()
.onHandleIntent()
and callWakefulBroadcastReceiver.completeWakefulIntent()
when finished.For example, a
BroadcastReceiver
that starts a wakefulService
:And the
Service
:Also, check out this article from the developer's guide on keeping the device awake.
On API level 23+ you have to deal with Doze.
From the documentation:
Unfortunately there is no alternative for
setRepeating()
, so you have two choices:As per Android developer document Note:
You need to use a
BroadcastReceiver
and a wakelock to reliably make this happen when the device is idle. Also, note that starting with API 19 alarms are inexact by default, which will play into this. if you are targeting API 21 or newer, consider usingJobScheduler
. Similar to this post Alarm Manager with 2 pending intents only 1 works?