Implementing an App Widget Provider

Now that the configuration is in place, you need to implement the App Widget. To do this, you need to extend the AppWidgetProvider class, which contains five methods that can be overridden:

► onUpdate()—This method is called at each update interval.

► onDeleted()—This method is called each time an App Widget is deleted.

► onEnabled()—This method is called the first time an App Widget is created, but not subsequent times.

► onDisabled()—This method is called when the last instance of an App Widget is deleted.

► onReceive()—This method is called for all received broadcast events; the default implementation calls each of the previous callback methods (e.g. onUpdate(), onDeleted(), onEnabled(), and onDisabled()) when necessary. This method can be overridden when advanced behavior is required.

For this example, you only need to override the onUpdate() method to update the RemoteViews object. No persistent setup is needed, so you don't need to override any of the other methods. That said, here's the implementation of the AppWidgetProvider class:

public class QuizWidgetProvider2 extends AppWidgetProvider { @Override public void onUpdate(Context context,

AppWidgetManager appWidgetManager, int[] appWidgetlds) { WidgetData widgetData = new WidgetData(MUnknown", "NA", ""); getWidgetData(widgetData);

String packageName = context.getPackageName(); RemoteViews remoteView =

new RemoteViews(context.getPackageName(), R.layout.widget); remoteView.setTextViewText(

R.id.widget_nickname, widgetData.nickname); remoteView.setTextViewText(

R.id.widget_score, "Score: 11 + widgetData.score); if (widgetData.avatarUrl.length() > 0) { URL image; try {

image = new URL(widgetData.avatarUrl);

Bitmap bitmap =

BitmapFactory.decodeStream(image.openStream()); if (bitmap == null) {

Log.w(DEBUG_TAG, "Failed to decode image"); remoteView.setImageViewResource(

R.id.widget_image, R.drawable.avatar);

remoteView.setImageViewBitmap(

R.id.widget_image, bitmap);

} catch (MalformedURLException e) {

Log.e(DEBUG_TAG, "Bad url in image", e); } catch (IOException e) {

Log.e(DEBUG_TAG, "IO failure for image", e);

remoteView.setImageViewResource(

R.id.widget_image, R.drawable.avatar);

ComponentName quizWidget =

new ComponentName(context, QuizWidgetProvider.class); AppWidgetManager appWidgetManager =

AppWidgetManager.getlnstance(context); appWidgetManager.updateAppWidget(quizWidget, remoteView); } catch (Exception e) {

Log.e(DEBUG_TAG, "Failed to update widget", e);

private void getWidgetData(WidgetData widgetData) { }

At this point, you need to get the data that will be displayed in the App Widget. The getWidgetData() method handles this by getting the player identifier from SharedPreferences and then downloading the data from the server. You handle the operation this way instead of loading this data straight from SharedPreferences so that you can switch it later to support loading data from friends or other players.

Next, you build up the RemoteViews object. The initialization requires not only the layout to use but also the package for where the layout comes from. Recall that a RemoteViews object will not be displayed in the same process, so more information is needed in order for it to access the resources.

You have access to the nickname and score information (or suitable default values), so you can set those via the setTextViewText() method, passing in both the identifier from the layout and the value. The code for the avatar image is similar but first verifies that a suitable URL for the avatar is available and that the image can be decoded. Finally, either the setImageViewBitmap() or setImageViewResource() method is called to apply the avatar image to the RemoteViews object.

Finally, you have to actually update the App Widget. You do this via a call to the updateAppWidget() method of AppWidgetManager. It requires both the RemoteViews object and the Android ComponentName object of the QuizWidgetProvider, retrieved by instantiating that class directly.

If you were paying close attention, you may have noticed that you didn't use two of the onUpdate() parameters: appWidgetManager and appWidgetIds. The appWidgetManager parameter isn't used because you'll be moving the code to a different method shortly, where an instance of it will be retrieved separately. The appWidgetIds parameter is used when you want to support multiple unique App Widgets that show different data. In that case, the application must track the appWidgetIds values, which are assigned by the system, separately and pair them correctly to the data that needs to be shown in each App Widget. Typically, this is done using a distinct configuration activity for each App Widget so the user controls what they want displayed in each different instance of this App Widget.

The App Widget should now appear in the Home screen's App Widget interface, as shown in Figure 18.1.

FIGURE 18.1

Adding the App Widget to the Home screen.

TVy It Yourself

To add an App Widget to the Home screen of an Android phone or the emulator, follow these easy steps:

1. Navigate to the Home screen.

2. Find a suitably empty area of the screen. (Remember that the App Widget needs 2x2 grid cells.)

3. Click and hold your finger (or the mouse button on the emulator) over the area where you want to add the App Widget.

4. When the pop-up menu appears, choose Add to Home Screen, Widgets.

5. Select the App Widget you just created (or any other App Widget) from the list and add it to your Home screen.

At this point, the App Widget looks as shown in Figure 18.2.

FIGURE 18.2

The Been There, Done That! App Widget.

0 0

Post a comment