所谓桌面小控件,就是指能直接显示在Android系统桌面的小程序,比如模拟时钟等。桌面小控件是通过Broadcast的形式来进行控制的,每个桌面小控件都对应一个BroadcastReceiver。Android提供了一个AppWidgetProvider类,它是BroadcastReceiver的子类,开发者只要开发一个继承AppWidgetProvider的子类,并重写其不同状态的生命周期方法即可。AppWidgetProvider提供如下四个不同的生命周期方法:

onUpdate:负责更新桌面控件的方法;实现桌面控件通常会考虑重写该方法。

onDeleted:当一个或多个桌面小控件被删除时回调该方法。

onEnabled:当接收到ACTION_APPWIDGET_ENABLED 广播时回调该方法。

onDisabled:当接收到ACTION_APPWIDGET_DISABLED广播时回调该方法。

开发桌面小控件步骤:

1、创建一个RemoteViews对象,创建该对象时可以指定加载指定的界面布局文件。

2、如果需要改变上一步所加载的界面布局文件的内容,可通过RemoteViews对象进行修改。一般来说,界面中主要包含ImageView和TextView两种组件。

3、创建一个ComponentName对象。

4、调用AppWidgetManager的updateAppWidget方法更新桌面小控件。

下面以开发数字时钟为例(代码原型来源疯狂讲义):

AppWidgetProvider子类:

package com.home;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.ComponentName;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.widget.RemoteViews;

public class DigitClock extends AppWidgetProvider {
	private Timer timer = new Timer();
	private AppWidgetManager appWidgetManager;
	private Context context;
	// 将0~9的液晶数字图片定义成数组
	private int[] digits = new int[] { R.drawable.image0, R.drawable.image1,
			R.drawable.image2, R.drawable.image3, R.drawable.image4,
			R.drawable.image5, R.drawable.image6, R.drawable.image7,
			R.drawable.image8, R.drawable.image9 };
	// 将显示小时、分钟、秒钟的ImageView定义成数组
	private int[] digitViews = new int[] { R.id.digit_image1,
			R.id.digit_image2, R.id.digit_image3, R.id.digit_image4,
			R.id.digit_image5, R.id.digit_image6 };

	@Override
	public void onUpdate(Context context, AppWidgetManager appWidgetManager,
			int[] appWidgetIds) {
		this.appWidgetManager = appWidgetManager;
		this.context = context;
		// 定义计时器
		timer = new Timer();
		// 启动周期性调度
		timer.schedule(new TimerTask() {

			@Override
			public void run() {
				// 发送空消息,通知界面更新
				handler.sendEmptyMessage(0x123);
			}
		}, 0, 1000);
	}

	private Handler handler = new Handler() {
		public void handleMessage(Message msg) {
			if (msg.what == 0x123) {
				RemoteViews views = new RemoteViews(context.getPackageName(),
						R.layout.digit);
				// 定义SimpleDateFormat对象
				SimpleDateFormat df = new SimpleDateFormat("HHmmss");
				// 将当前时间格式化成HHmmss的形式
				String timeStr = df.format(new Date());
				for (int i = 0; i < timeStr.length(); i++) {
					// 将第i个数字字符转换成对应的数字
					int num = timeStr.charAt(i) - 48;
					// 将第i个图片设为对应的液晶数字图片
					views.setImageViewResource(digitViews[i], digits[num]);
				}
				// 将AppWidgetProvider子类实例包装成ComponentName对象
				ComponentName componentName = new ComponentName(context,
						DigitClock.class);
				// 调用AppWidgetManager将remoteViews添加到ComponentName中
				appWidgetManager.updateAppWidget(componentName, views);
				super.handleMessage(msg);
			}
		}
	};
}

布局文件(digit.xml):

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal" >

    <ImageView
        android:id="@+id/digit_image1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <ImageView
        android:id="@+id/digit_image2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <ImageView
        android:id="@+id/digit_image7"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:src="@drawable/image" />

    <ImageView
        android:id="@+id/digit_image3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <ImageView
        android:id="@+id/digit_image4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <ImageView
        android:id="@+id/digit_image8"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:src="@drawable/image" />

    <ImageView
        android:id="@+id/digit_image5"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <ImageView
        android:id="@+id/digit_image6"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>

配置receiver:

<receiver
            android:name="com.home.DigitClock"
            android:label="@string/app_name" >
            <!-- 将该BroadcastReceiver当成桌面下控件 -->
            <intent-filter>
                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
            </intent-filter>
            <!-- 指定桌面小控件的meta-data -->
            <meta-data
                android:name="android.appwidget.provider"
                android:resource="@xml/appwidget_provider" />
        </receiver>

appwidget_provide.xml:

<?xml version="1.0" encoding="utf-8"?>
<!--
指定该桌面组件的基本配置信息:
 minWidth:桌面小控件的最小宽度
 minHeight:桌面小控件的最小高度
 updatePeriodMillis:更新频率
initialLayout:初始时显示的布局
-->
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:initialLayout="@layout/digit"
    android:minHeight="70dp"
    android:minWidth="150dp"
    android:updatePeriodMillis="1000" />