I have a widget which shows the data usage, for this I have created a PreferenceActivity where the user can choose from various update frequencies.. I get the chosen freq value from SharedPreferences and with that I start an alarm but I get weird result. Here is my AppWidgetProvider:
private static PendingIntent pendingIntent = null;
...
public void onReceive(Context context, Intent intent) {
Log.d("TAG", "receive");
super.onReceive(context, intent);
if (CLOCK_WIDGET_UPDATE.equals(intent.getAction())) {
ComponentName thisAppWidget = new ComponentName(context.getPackageName(), getClass().getName());
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
int ids[] = appWidgetManager.getAppWidgetIds(thisAppWidget);
for (int appWidgetID : ids) {
updateAppWidget(context, appWidgetManager, appWidgetID);
}
}
}
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
Log.d("TAG", "update");
super.onUpdate(context, appWidgetManager, appWidgetIds);
for (int i = 0; i < appWidgetIds.length; i++) {
int appWidgetId = appWidgetIds[i];
updateAppWidget(context, appWidgetManager, appWidgetId);
}
}
public static void updateAppWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId) {
// starting timer
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.cancel(pendingIntent);
Intent intent = new Intent(CLOCK_WIDGET_UPDATE);
pendingIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
SharedPreferences prefs = context.getSharedPreferences(Integer.toString(appWidgetId), Context.MODE_PRIVATE);
int updateFrequencyMin = Integer.parseInt(prefs.getString(KEY_UPDATE_FREQ, DEFAULT_UPDATE_FREQ));
Log.d("TAG", "Update freq: " + updateFrequencyMin);
long updateFrequencyMillis = updateFrequencyMin * 60 * 1000;
// alarmManager.cancel(pendingIntent);
alarmManager.setInexactRepeating(AlarmManager.RTC, System.currentTimeMillis(), updateFrequencyMillis,
pendingIntent);
....
appWidgetManager.updateAppWidget(appWidgetId, view);
}
public void onDisabled(Context context) {
AlarmManager m = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
m.cancel(pendingIntent);
}
If I set the update frequency to 5 minutes with InexactRepeating, I get this log:
08-18 15:30:17.902: D/TAG(23624): receive
08-18 15:30:18.122: D/TAG(23624): receive
08-18 15:30:18.122: D/TAG(23624): update
08-18 15:30:18.122: D/TAG(23624): Update freq: 60
08-18 15:30:22.582: D/TAG(23624): receive
08-18 15:30:22.602: D/TAG(23624): Update freq: 60
08-18 15:30:33.272: D/TAG(23624): receive
08-18 15:30:33.282: D/TAG(23624): Update freq: 60
08-18 15:30:39.692: D/TAG(23624): receive
08-18 15:30:39.692: D/TAG(23624): Update freq: 60
08-18 15:31:33.292: D/TAG(23624): receive <--- I have chosen the freq
08-18 15:31:33.292: D/TAG(23624): Update freq: 5
08-18 15:31:39.962: D/TAG(23624): receive
08-18 15:31:39.962: D/TAG(23624): Update freq: 5
I don't know why the onReceive and the onUpdate are called multiple times when I am on the configuration activity.
With the setRepeat method it is worse as you can see the timestamps:
08-18 15:38:59.992: D/TAG(24011): receive
08-18 15:39:00.242: D/TAG(24011): receive
08-18 15:39:00.242: D/TAG(24011): update
08-18 15:39:00.252: D/TAG(24011): Update freq: 60
08-18 15:39:00.442: D/TAG(24011): receive
08-18 15:39:00.442: D/TAG(24011): Update freq: 60
08-18 15:39:00.562: D/TAG(24011): receive
08-18 15:39:00.562: D/TAG(24011): Update freq: 60
08-18 15:39:00.642: D/TAG(24011): receive
08-18 15:39:00.642: D/TAG(24011): Update freq: 60
08-18 15:39:00.652: D/TAG(24011): receive
08-18 15:39:00.652: D/TAG(24011): Update freq: 60
08-18 15:39:00.662: D/TAG(24011): receive
08-18 15:39:00.662: D/TAG(24011): Update freq: 60
And finally, this is my preference activity:
public class DataStatWidgetConfigure extends PreferenceActivity {
private int widgetId;
@SuppressWarnings("deprecation")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle extras = getIntent().getExtras();
if (extras != null) {
widgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
Log.d("meeegy", Integer.toString(widgetId));
getPreferenceManager().setSharedPreferencesName(Integer.toString(widgetId));
addPreferencesFromResource(R.xml.prefs);
}
}
@Override
public void onBackPressed() {
Intent resultValue = new Intent();
resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId);
setResult(RESULT_OK, resultValue);
finish();
}
}
From what I see in your code, you never cancel your previous alarms when you update your widget. So you keep adding more and more callback to AlarmManager. Try removing the previous call back and then add a new one
The problem was with this:
The second parameter is when need to be called first, System.currentTimeMillis() means now, so right after this in OnReceive() called updateAppWidget() which called this setInexactRepeating() again immediately, and so on..
A solution: