3

I'm developing a live wallpaper for Android. To refresh the wallpaper at set times I use AlarmManager. Most of the times this works great, but occasionally my alarm isn't received. On top of that I can't replicate this behaviour, it just randomly happens. I've run into this using at least 3 ROMs.

Now for the code.
I use this PendingIntent:

mRefreshIntent = new Intent()
    .setComponent(new ComponentName(mContext, RefreshBroadcastReceiver.class))
    .setAction("my.package.name.REFRESH_WALLPAPER");
mPendingRefreshIntent = PendingIntent.getBroadcast(
    mContext, 
    0, 
    mRefreshIntent, 
    PendingIntent.FLAG_CANCEL_CURRENT);

This is my code to set the alarm:

mAlarmManager.set(AlarmManager.RTC_WAKEUP, time, mPendingRefreshIntent);

where time is the UTC time in milliseconds. I often verified if the alarm is set as intended using adb shell dumpsys alarm, which it is.

The receiving side:

public class RefreshBroadcastReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d("DayNight", "onReceive     ; " + System.currentTimeMillis());
        DayNightService.refresher.refresh();
        Log.d("DayNight", "onReceive done; " + System.currentTimeMillis());
    }
}

Associated manifest lines:

<application>
    ...
    <receiver
        android:name="RefreshBroadcastReceiver">
        <intent-filter>
            <action android:name="my.package.name.REFRESH_WALLPAPER" />
        </intent-filter>
    </receiver>
    ...
</application>

Alarms which are not fired always exist in the queue (dumpsys alarms) beforehand, and are not in the alarm log afterwards. Seems like they get 'lost' at T minus zero.

I will be very happy if one of you can solve this problem for me.

Thomas
  • 1,508
  • 2
  • 22
  • 35

1 Answers1

2

I use following code:

  Intent intent = new Intent(ACTION);
    PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_NO_CREATE);
    Log.d(LOG_TAG, "pending intent: " + pendingIntent);
    // if no intent there, schedule it ASAP
    if (pendingIntent == null) {
        pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
        // schedule new alarm in 15 minutes
        alarmService.setInexactRepeating(AlarmManager.RTC, System.currentTimeMillis(),300000, pendingIntent);
        Log.d(LOG_TAG, "scheduled intent: " + pendingIntent);
    }

Note, that I request inexact repeating alarm and RTC ( not RTC_WAKEUP ) - if phone is sleeping deep inside jeans pocket, user is not interested on changes of your live wallpaper - no need to waste battery juice and wake phone up

You may also need to register boot complete broadcast receiver to start update scheduling on reboot.

Konstantin Pribluda
  • 12,329
  • 1
  • 30
  • 35
  • This is not really what I'm looking for: the refresh intervals are different each time and I'm not (yet) concerned about battery life (I could replace RTC_WAKEUP with RTC if I were). Maybe you could point out where exactly there is an error in my code or a bug in AlarmManager? – Thomas Dec 09 '11 at 15:27
  • Where do you activate this intent? – Konstantin Pribluda Dec 09 '11 at 15:46
  • The first one in `WallpaperService.WallpeperEngine.onCreate()`. The next alarm is set when the previous is triggered, and so on. – Thomas Dec 09 '11 at 15:55