Logo Icon Logo
A Crowd-sourced Cookbook on Writing Great Android® Apps
GitHub logo Twitter logo OReilly Book Cover Art

Creating a Simple App Widget

Published? true
FormatLanguage: WikiFormat

Problem:

Widgets are simple graphical user interfaces that allow users to easily interact with an existing application (activity and/or service). It's rather simple to create one. Just try it!

Solution:

A guided list of steps with a simple example that allows you to create a widget that starts a service that updates its visual components.

Example: CurrentMoodWidget. A simple solution that presents the current mood in the form of a smiley text in a widget. The current mood smiley changes to a random mood smiley whenever the user clicks the update button (smiley image button).

Initial
Initial Mood

Mood Updated
Current Mood

Discussion:

Following these steps you will be able to create a widget that calls a service and updates its visual components.

1. Create a new Android Project (CurrentMoodWidgetProject)

  • "Current Mood" as the application name;
  • oreillymedia.cookbook.android.spikes for the package name;
  • Do not create an activity;
  • Minimum SDK version: 8 (for Android 2.2).

2. Add the text support required for the widget. Place this under the resources files folder (res/values/string.xml), according to the following name-value pairs.

  • widgettext - "current mood:"
  • widgetmoodtext - ":)"

3. Add the image(s) that will appear in the widget's button. Place these under the res/drawable structure (smile_icon.png).

4. Create a new layout file inside res/layout. Place these under the project structure, that will define the widget layout (widgetlayout.xml) according to the following structure.

	<TextView android:text="@string/widgettext" 
                  android:layout_width="0dp"
                  android:layout_height="wrap_content"
                  android:layout_weight="0.8"
                  android:layout_gravity="center_vertical"
                  android:textColor="#000000"></TextView>
	<TextView android:text="@string/widgetmoodtext"
                  android:id="@+id/widgetMood" android:layout_width="0dp" 
                  android:layout_height="wrap_content" 
                  android:layout_weight="0.3" 
                  android:layout_gravity="center_vertical" 
                  android:textColor="#000000"></TextView>
	<ImageButton android:id="@+id/widgetBtn" android:layout_width="0dp" 
                  android:layout_height="wrap_content" 
                  android:layout_weight="0.5" android:src="@drawable/smile_icon" 
                  android:layout_gravity="center_vertical"></ImageButton>

5. Now, you should provide the widget provider setup configuration:

  • Create the res/xml folder under the project structure
  • Create a xml file (widgetproviderinfo.xml) with the following parameters:
       <appwidget-provider
           xmlns:android="http://schemas.android.com/apk/res/android" 
           android:minWidth="220dp" 
           android:minHeight="72dp"
           android:updatePeriodMillis="86400000" 
           android:initialLayout="@layout/widgetlayout">
       </appwidget-provider>

6. Now you should create the service that reacts to the user interaction with the smiley image button (CurrentMoodService.java).

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		super.onStart(intent, startId);
                updateMood(intent);
		stopSelf(startId);
		return START_STICKY;
	}

	private void updateMood(Intent intent) {
           if (intent != null){
    		String requestedAction = intent.getAction();
    		if (requestedAction != null &&  requestedAction.equals(UPDATEMOOD)){
	            this.currentMood = getRandomMood();
	            int widgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, 0);
	            AppWidgetManager appWidgetMan = AppWidgetManager.getInstance(this);
	            RemoteViews views = new RemoteViews(this.getPackageName(),R.layout.widgetlayout);
	            views.setTextViewText(R.id.widgetMood, currentMood);
	            appWidgetMan.updateAppWidget(widgetId, views);  
    		}
           }
       }

7. After defining the service, it is time to implement the widget provider class (CurrentMoodWidgetProvider.java).

        @Override
	public void onUpdate(Context context, AppWidgetManager appWidgetManager,
			int[] appWidgetIds) {
		super.onUpdate(context, appWidgetManager, appWidgetIds);
		
		for (int i=0; i<appWidgetIds.length; i++) {
		    int appWidgetId = appWidgetIds[i];
		    RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widgetlayout);
		    Intent intent = new Intent(context, CurrentMoodService.class);
		    intent.setAction(CurrentMoodService.UPDATEMOOD);
		    intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
		    PendingIntent pendingIntent = PendingIntent.getService(context, 0, intent, 0);
		    views.setOnClickPendingIntent(R.id.widgetBtn, pendingIntent);
		    appWidgetManager.updateAppWidget(appWidgetId, views);
		}
	}	

8. Finally it is necessary to declare the Service and the App Widget Provider in the Manifest (AndroidManifest.xml).

	
    	<service android:name=".CurrentMoodService">
    	</service>
	<receiver android:name=".CurrentMoodWidgetProvider">
	    <intent-filter>
	        <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
	    </intent-filter>
	    <meta-data android:name="android.appwidget.provider"
	               android:resource="@xml/widgetproviderinfo" />
	</receiver>

Download:

The source code for this project can be downloaded from http://sites.google.com/site/androidsourcecode/src/CurrentMoodWidgetProject.rar.