0

I need to know the widget id inside onReceive(). I thought to associate the selected item informations of the configure activity to the new widget id, and then save them to sharedpreferences so that i can know what to do inside onReiceive() by reading from sharedpreferences

Configure activity:

resultValue = new Intent();
resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetId);
setResult(RESULT_CANCELED, resultValue);

listView.setOnItemClickListener(new OnItemClickListener()
{
    public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3)
    {
        ...
        resultValue.putExtra("mykey", "otherinfo");
        setResult(RESULT_OK, resultValue);
        finish();
    }           
});

AppWidgetProvider:

@Override
public void onEnabled(Context context)
{
    super.onEnabled(context);
    AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
    Intent intent = new Intent(context, AlarmManagerBroadcastReceiver.class);
    int id = intent.getStringExtra(AppWidgetManager.EXTRA_APPWIDGET_ID) // <-- THIS IS NULL!

    // save id on shared preferences

    PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, 0);   
    am.setInexactRepeating(AlarmManager.RTC, System.currentTimeMillis(), UPDATE_INTERVAL, pi);      
}

BroadCastReceiver:

public void onReceive(Context context, Intent intent)
{       
    intent.getStringExtra(AppWidgetManager.EXTRA_APPWIDGET_ID); // <-- NULL
    ..  
}

getStringExtra returns always null values... maybe the code above is completely wrong

filippo
  • 839
  • 2
  • 13
  • 25
  • Before you do int id = intent.getString... you create the Intent. So the Intent has no infos in it! It's completely logical that you get an NPE. Also do the following: PendingIntent.FLAG_UPDATE_CURRENT use this flag as your last parameter of the Pending Intent! – Pavlos Aug 14 '13 at 14:46

1 Answers1

2

A few things...

  1. onEnabled in an AppWidgetProvider is only called once when the first appwidget is added (that's when this AppWidgetProvider becomes "enabled"). Notice that onEnabled doesn't give you an appWidgetId - it's not a callback associated with a particular instance of an app widget on the home screen.
  2. You are calling getStringExtra(AppWidgetManager.EXTRA_APPWIDGET_ID) on an Intent you've just created. I think you meant to call putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId). However, as mentioned above, this won't work either since you aren't given an id in onEnabled().

If you want to set an alarm that is associated to each appwidget instance on the home screen, you need to do some extra work.

  1. When you finish configuring an app widget, store its appWidgetId in SharedPreferences (you could use the key "appwidgetid_##" to store a boolean value, for instance).
  2. When onUpdate() is called and you are iterating over the appWidgetIds array, check each appWidgetId in SharedPreferences first. If the check passes, you know the user has configured that appWidget and you can create and set your alarm for it; otherwise, continue to the next appWidgetId.
  3. When setting the alarm, note that Intents must be unique when creating PendingIntents, otherwise you'll get a PendingIntent that reuses or overwrites the old one (depending on which flag you specify as the last argument to the PendingIntent call). Since extras are not considered when checking for uniqueness, see the code at the bottom for how to make it unique.
  4. In onDelete(), cancel the alarm for that appwidget. Make sure you construct the PendingIntent the exact same way. You can also remove the appWidgetId from SharedPreferences here.

To make the intent unique:

Intent intent = new Intent(context, AlarmManagerBroadcastReceiver.class);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWIdgetId);
// IMPORTANT!
intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
// Note the FLAG_UPDATE_CURRENT
PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager am = ...
am.setInexactRepeating(...);
Karakuri
  • 38,365
  • 12
  • 84
  • 104
  • Thanks for replying, now my problem is that onUpdate is called before the configure activity finishes, and so the alarm can never being started... – filippo Aug 14 '13 at 20:13
  • Is it not calling `onUpdate()` again after configuration is complete? I suppose you could force the `onUpdate()` yourself by broadcasting an Intent with the `AppWidgetManager.ACTION_APPWIDGET_UPDATE` action and the `appWidgetId` as an extra. Or write a public static method to update the appwidget. Your `onUpdate()` method can call it, and so can your configuration activity. That way either one will start the alarms (`onUpdate()` will start it after device reboot, for instance). – Karakuri Aug 14 '13 at 23:00
  • I tried to call sendBroadcast(resultValue), but nothing happens, while with the static method when onReceive() is called if for example i've two widgets, they are both updated with the same data. Maybe there is something wrong with the context? In my static method StartAlarm(Context context, int widgetId), i use the configure activity context... – filippo Aug 16 '13 at 09:52