Creating and Using a Widget Configuration Activity

In some cases an App Widget will be significantly more useful if the user is given the opportunity to customize the data it displays and how the data is displayed. This is particularly important given that multiple instances of the same widget can be added to the home screen.

An App Widget configuration Activity is an Activity that is launched immediately when a widget is added to the home screen. It can be any Activity within your application, provided it has an Intent Filter for the APPWIDGET_CONFIGURE action, as shown here:

<activity android:name=". MyWidgetConfigurationActivity"> <intent-filter>

<action android:name="android.apwidget.action.APPWIDGET_CONFIGURE"/> </intent-filter> </activity>

It must also return a result Intent that includes an extra that describes the App Widget ID of the widget it is configuring using the extra_appwidget_id constant. This extra is included in the Intent that launches the Activity.

Intent result = new Intent();

result.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);

setResult(RESULT_OK, result);

To assign a completed configuration Activity to a widget you must add it to the widget settings file using the configure tag. The activity must be specified by its fully qualified package name, as shown here:

<?xml version="1.0" encoding="utf-8"?> <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"

android:initialLayout="@layout/my_widget_layout"

android:minWidth="146dp"

android:minHeight="146dp"

android:label="My App Widget"

android:updatePeriodMillis="3 600000"

android:configure="com.paad.chapter9.MyWidgetConfigurationActivity"

CREATING AN EARTHQUAKE WIDGET

The following instructions show you how to create a new home-screen widget to display details for the latest earthquake detected. The UI for this widget is simple to the point of being inane; this is a side effect of keeping the example as concise as possible. Note that it does not conform to the widget style guidelines.

Once completed and added to the home screen, your widget will appear as in Figure 10-2.

Using a combination of the update techniques described above, this widget listens for broadcast Intents that announce an update has been performed and sets the minimum update rate to ensure it is updated once per day regardless.

The following code extends the Earthquake application last seen in Chapter 8:

1. Start by creating the layout for the widget UI as an XML resource. Use a Linear Layout to configure Text Views that display the quake magnitude and location:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="#F111" android:padding="5sp"> <TextView android:id="@+id/widget_magnitude" android:layout_width="wrap_content"

Android Appwidgetmanager
FIGURE 10-2

android:layout_height="fill_parent"

android:textSize="24sp"

android:padding="3dp"

<TextView android:id="@+id/widget_details"

android:layout_width="fill_parent"

android:layout_height="fill_parent"

android:textSize="14sp"

android:padding="3dp"

</LinearLayout>

2. Create a stub for a new EarthquakeWidget class that extends AppWidgetProvider. You'll return to this class to update your widget with the latest quake details.

package com.paad.earthquake;

import android.widget.RemoteViews; import android.appwidget.AppWidgetManager; import android.appwidget.AppWidgetProvider; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.database.Cursor;

public class EarthquakeWidget extends AppWidgetProvider { }

3. Create a new widget definition file, quake_widget_info.xml, and place it in the res/xml folder. Set the minimum update rate to 24 hours and set the widget dimensions to two cells wide and one cell high — 146dpx74dp. Use the widget layout you created in Step 1 for the initial layout.

<?xml version="1.0" encoding="utf-8"?> <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"

android:initialLayout="@layout/quake_widget"

android:minWidth="146dp"

android:minHeight="74dp"

android:label="Last Earthquake"

android:updatePeriodMillis="86400000"

4. Add your widget to the application manifest, including a reference to the widget definition resource you created in Step 3, and registering an Intent Filter for the App Widget update action.

<receiver android:name="EarthquakeWidget" android:label="Last Earthquake"> <intent-filter>

<action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> </intent-filter>

<meta-data android:name="android.appwidget.provider" android:resource="@xml/earthquake_widget_info"

</receiver>

Your widget is now configured and will be available to add to the home screen. You now need to update the EarthquakeWidget class from Step 2 to update the widget to display the details of the latest quake.

5. Start by creating two new updateQuake methods within the Earthquake Widget class:

5.1. The first should take an App Widget Manager and an array of widget IDs as well as the context. Later you'll extend this second stub to update the widget appearance using Remote Views.

public void updateQuake(Context context,

AppWidgetManager appWidgetManager, int[] appWidgetlds) {

5.2. The second method stub should take only the context, using that to obtain an instance of the AppWidgetManager. Then use the App Widget Manager to find the widget IDs of the active Earthquake widgets, passing both into the method you created in Step 5.1.

public void updateQuake(Context context) {

ComponentName thisWidget = new ComponentName(context,

EarthquakeWidget.class);

AppWidgetManager appWidgetManager =

AppWidgetManager.getlnstance(context); int[] appWidgetlds = appWidgetManager.getAppWidgetlds(thisWidget); updateQuake(context, appWidgetManager, appWidgetlds);

5.3. Within the updateQuake stub from Step 5.1, use the Earthquake Content Provider created in Chapter 6 to retrieve the newest quake and extract its magnitude and location:

public void updateQuake(Context context,

AppWidgetManager appWidgetManager, int[] appWidgetlds) {

Cursor lastEarthquake;

ContentResolver cr = context.getContentResolver(); lastEarthquake = cr.query(EarthquakeProvider.CONTENT_URI, null, null, null, null);

String magnitude = "--"; String details = "-- None --";

if (lastEarthquake.moveToFirst()) {

magnitude =

lastEarthquake.getString(EarthquakeProvider.MAGNITUDE_COLUMN); details =

lastEarthquake.getString(EarthquakeProvider.DETAILS_COLUMN); }

finally {

lastEarthquake.close();

5.4. Create a new RemoteViews object to set the text displayed by the widget's Text View elements to show the magnitude and location of the last quake:

public void updateQuake(Context context,

AppWidgetManager appWidgetManager, int[] appWidgetlds) {

Cursor lastEarthquake;

ContentResolver cr = context.getContentResolver(); lastEarthquake = cr.query(EarthquakeProvider.CONTENT_URI, null, null, null, null);

String magnitude = "--"; String details = "-- None --";

if (lastEarthquake.moveToFirst()) { magnitude =

lastEarthquake.getString(EarthquakeProvider.MAGNITUDE_COLUMN); details =

lastEarthquake.getString(EarthquakeProvider.DETAILS_COLUMN); }

finally {

lastEarthquake.close();

final int N = appWidgetlds.length; for (int i = 0; i < N; i++) {

int appWidgetId = appWidgetIds[i];

RemoteViews views = new RemoteViews(context.getPackageName(),

R.layout.quake_widget); views.setTextViewText(R.id.widget_magnitude, magnitude); views.setTextViewText(R.id.widget_details, details); appWidgetManager.updateAppWidget(appWidgetId, views);

7.1. Start by updating the doRefreshEarthquakes method in the EarthquakeService to broadcast an Intent when it has completed.

public static String QUAKES_REFRESHED = "com.paad.earthquake.QUAKES_REFRESHED";

public void doRefreshEarthquakes() {

[ ... Existing doRefreshEarthquakes code ... ] sendBroadcast(new Intent(QUAKES_REFRESHED));

7.2. Override the onReceive method in the EarthquakeWidget class, but be sure to call through to the superclass to ensure that the standard widget event handlers are still triggered:

@Override public void onReceive(Context context, Intent intent){ super.onReceive(context, intent);

7.3. Add a check for the quakes_refreshed action you broadcast in Step 7.1, and call updateQuakes when it's received:

@Override public void onReceive(Context context, Intent intent){ super.onReceive(context, intent);

if (intent.getAction().equals(EarthquakeService.QUAKES_REFRESHED)) updateQuake(context);

7.4. Finally, add an Intent Filter for this Intent action to the widget's manifest entry:

<receiver android:name="EarthquakeWidget" android:label="Last

Earthquake">

<intent-filter>

<action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> </intent-filter> <intent-filter>

Override the onUpdate handler to call updateQuake: @Override public void onUpdate(Context context,

AppWidgetManager appWidgetManager, int[] appWidgetIds) { updateQuake(context, appWidgetManager, appWidgetIds);

Your widget is now ready to be used, and will update with new earthquake details when added to the home screen and once every 24 hours thereafter.

Now enhance the widget to update whenever the Earthquake Service you created in Chapter 8 has refreshed the earthquake database:

<action android:name="com.paad.earthquake.QUAKES_REFRESHED" /> </intent-filter>

<meta-data android:name="android.appwidget.provider" android:resource="@xml/earthquake_widget_info"

</receiver>

Your widget will now update once per day, and every time the Earthquake Service performs a lookup.

To enhance the Earthquake Widget, consider how you could use Layered Drawables within an Image View to indicate the magnitude of the earthquake being shown. Figure 10-3 shows one possibility.

INTRODUCING LIVE FOLDERS

Live Folders are a unique and powerful means by which your applications can expose data from their Content Providers directly on the home screen. They provide dynamic shortcuts to information stored in your application.

When added, a Live Folder is represented on the home screen as a shortcut icon. Selecting the icon will open the Live Folder, as shown in Figure 10-4. This figure shows a Live Folder open on an Android home screen, in this case the starred contacts list.

FIGURE 10-3

To iSi/i/ ¿7 L/Ve Folder to the home screen, long-press a piece of empty space and select Folders. You will be presented with a list of available Live Folders; click one to select and add. Once it is added, click to open the Live Folder, and long-press to move the shortcut.

Mobile Apps Made Easy

Mobile Apps Made Easy

Quick start guide to skyrocket your offline and online business success with mobile apps. If you know anything about mobile devices, you’ve probably heard that famous phrase coined by one of the mobile device’s most prolific creators proclaiming that there’s an app for pretty much everything.

Get My Free Training Guide


Post a comment