Ok… I started to do some Android devel… And I started to like it, even if it is based on Java, works in Eclipse and has a ton of classes.
Now, the first project is a widget (weather widget). For this, there’s this “AppWidgetProvider” class that implements the design and functions for data retrieval (using threads), and also a configuration Activity. When the configuration activity finishes (a “Save” button is pressed), a static function of the AppWidgetProvider class is called. This static function updates the settings of the widget and also does something of interest: it sets the event handler for “onClick” – so that when I click (touch) the widget, to be able to modify the layout somehow (to rotate a needle).
This is a part of the static function that updates the widget:
...
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
Intent clickIntent = new Intent(context, DigiStation.class);
clickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, appWidgetId, clickIntent, 0);
views.setOnClickPendingIntent(R.id.widget_normal_relativelayout, pendingIntent);
appWidgetManager.updateAppWidget(appWidgetId, views);
...
The AppWidgetProvider class is called “DigiStation” – we’re using it for creating an intent that targets it.
Ok. For handling the events, the DigiStation class (which is of type AppWidgetProvider) implements the function “onReceive”. The function is called with two parameters: the context and the intent.
Now, the issue was to be able to distinguish between multiple instances of the same AppWidgetProvider class. To be able to do that, I had to put some extra information in the intent (clickIntent.putExtra). The field contains the appWidgetId – the widget ID – of the instance.
The onReceive function looks like this:
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction()==null) {
Bundle extras = intent.getExtras();
if(extras!=null) {
int widgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
// do something for the widget that has appWidgetId = widgetId
}
}
else {
super.onReceive(context, intent);
}
}
All looks simple enough, but there are some little details that I must underline, because I spend a few days with them:
1. To be able to distinguish between multiple instances of the same AppWidgetProvider, when registering the “onClick” event (intent) you must add an extra value with the widget ID (appWidgetId)
2. Update only the views of the current instance! – appWidgetManager.updateAppWidget(appWidgetId, views);
3. Android reuses intents, so when you create an intent, make sure you put an unique ID, or else the same intent used before will be triggered for all instances! Only with this detail I spent half a day! ( PendingIntent pendingIntent = PendingIntent.getBroadcast(context, appWidgetId, clickIntent, 0); )
4. When handling the click event, get the appWidgetId from the “extras” payload of the intent.
Hope this helps people not spending so much time for little undocumented details! :)
Enjoy!