6

I want to make some external service monitor and be notified on problems as fast as possible.

I tried to set up AlarmManager with 1-2 minutes interval, but it looks like it fires randomly every several minutes.

Of course, I want to be safe from killing my background task by android, which would stop monitoring if I just use Service.

Is it possible to use AlarmManager in small, accurate intervals?

Which approaches are used in applications like Facebook, Gmail to notify about new messages?

Would it be better to make Service with startForeground and partial WakeLock?

Piotr Müller
  • 5,323
  • 5
  • 55
  • 82

3 Answers3

8

I tried to set up AlarmManager with 1-2 minutes interval, but it looks like it fires randomly every several minutes.

Since you decided not to show how you "set up AlarmManager with 1-2 minutes interval", it will be difficult for anyone to help you. Please read the documentation for AlarmManager and note the default-inexact behavior new to Android 4.4.

I want to be safe from killing my background task by android, which would stop monitoring if I just use Service.

AlarmManager does not solve all problems in this regard. For example, if the user elects to force-stop your app (e.g., via Settings), your alarms are removed.

Is it possible to use AlarmManager in small, accurate intervals?

Use setRepeating() on Android 1.0-4.3 and setExact() on Android 4.4+. With setExact(), as part of processing one alarm event, you will need to schedule the next alarm event.

Would it be better to make Service with startForeground and partial WakeLock?

Only if your device is always plugged into power (e.g., industrial process monitor).

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • You do not need to worry about 4.4 and plus, separately if you set your target version to be lower than 4.4. – Parth Kapoor Jun 17 '14 at 13:01
  • 2
    @Eu.Dr.: Correct. However, there are many factors involved in choosing a `targetSdkVersion`. Savvy programmers take into account that, someday, they will need to raise their `targetSdkVersion` and will forget about its impact on alarms. Such programmers will therefore opt into `setExact()` at the point in time of developing new `AlarmManager` code, where exact alarms are needed. `targetSdkVersion` is mostly to ease the transition for already-existing code, not as a license to ignore changes when writing new code. – CommonsWare Jun 17 '14 at 13:12
  • 1
    Will accept this but I cannot achieve 1 minute interval at all, even on adroid 3 target SDK. This can be related to that I'm using MIUI Android, it looks like there is some internal limit equals exacly to 5 minutes as the smallest alarm interval – Piotr Müller Jun 18 '14 at 08:22
  • 1
    @killer_PL: I have used `AlarmManager` for demonstrations set as low as five seconds, so it's certainly capable of it. But `AlarmManager` is an area where device manufacturers make changes to try to extend battery life, so it would not surprise me if your device is the source of your problem. You might compare against the x86 emulator, or another device, or something. – CommonsWare Jun 18 '14 at 10:47
  • `setRepeating()` does not work reliably on Android 5 and higher on some devices, even if you set your `targetSdk` to 8 (Android 2.2). Most newer devices seem to ignore the `targetSdk` setting for this and use their own power-management algorithms. Unfortunately. – David Wasser Nov 17 '16 at 11:02
1
Calendar cal = Calendar.getInstance();
            cal.add(Calendar.SECOND, 30);
            Intent intent = new Intent(MainActivity.this, YourClass.class);
            PendingIntent pintent = PendingIntent.getService(MainActivity.this,
                    0, intent, 0);
            AlarmManager alarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
            alarm.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(),
                    60* 1000, pintent);
Manikandan
  • 1,802
  • 5
  • 20
  • 28
0

Posting a code snippet that we have used.Please modify as per your requirement. We use it for every 15 seconds and it works.

public class AlarmManagerBroadcastReceiver extends BroadcastReceiver  
{
private static final int _REFRESH_INTERVAL = 60 * 1; // 1 minutes
// Alarm id
    private static final int ALARM_ID = 102; // This can be any random integer.

    PendingIntent pi = null;
    AlarmManager am= null;

@Override
    public void onReceive(Context context, Intent intent) 
    {
        /* All actions to be handled here.. */
        }


    // This is to initialize the alarmmanager and the pending intent. It is done in separate method because, the same alarmmanager and
    // pending intent instance should be used for setting and cancelling the alarm.

    public void SetContext(Context context)
    {
        this.context = context;
        am=(AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        Intent intent = new Intent(context, AlarmManagerBroadcastReceiver.class);
        pi = PendingIntent.getBroadcast(context, ALARM_ID, intent, PendingIntent.FLAG_UPDATE_CURRENT);
    }

    // Setting the alarm to call onRecieve every _REFRESH_INTERVAL seconds
    public void SetAlarm()
    {
        // am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 1000 * _REFRESH_INTERVAL , pi);
        try
        {
            am.cancel(pi);
        }catch (Exception ignored){}
        am.setRepeating(AlarmManager.RTC_WAKEUP, SystemClock.elapsedRealtime(), 1000 * _REFRESH_INTERVAL , pi);
    }

    // Cancel the alarm.
    public void CancelAlarm()
    {
        am.cancel(pi);
    }

}
ngrashia
  • 9,869
  • 5
  • 43
  • 58
  • This solution is same as mine - and it fires up exactly every 5 minutes. – Piotr Müller Jun 17 '14 at 13:27
  • Note two things: 1) Starting at API 19, all alarms are inexact; 2) In order for this to work over long periods of time, the broadcast receiver must be registered in the manifest, not dynamically – G. Blake Meike Jun 17 '14 at 13:44