桌面控件是通过BroadCast的形式进行控制的,因此每个桌面控件都对应一个BroadCastReceiver.为了简化桌面控件的开发,Android提供了一个AppWidgetProvider类,它就是BroadcastReceiver的子类.
为了开发桌面控件,开发者只要开发一个继承AppWidgetProvider的子类,并重写AppWidgetProvider不同的生命周期方法即可.
AppWidgetProvider提供如下4个不同的生命周期方法:
onUpdate():负责更新桌面的方法;实现桌面控件通常会考虑重写该方法
onDeleted():当一个或多个桌面控件被删除时回调该方法
onEnabled():当接收到ACTION_APPWIDGET_ENABLED BroadCast时回调该方法.
onDisabled():当接收到ACTION_APPWIDGET_DISABLED BroadCast时回调该方法.
一般来说,开发桌面控件只需要定义一个AppWidgetProvider的子类,并重写它的OnUpdate()方法即可,重写该方法的步骤如下:
创建一个RemoteViews对象,创建该对象时可以指定加载指定的界面布局文件
如果需要改变上一步所加载的界面布局文件的内容,可通过RemoteViews对象进行修改
创建一个ComponentName对象
调用AppWidgetManager更新桌面控件
以上步骤即:使用AppWidgetManager通过RemteViews来更新AppWidgetProvider的子类实例(需要将它包装成COmponentName对象)
开发Widget步骤如下:
创建小插件的布局(layout)
创建小插件的属性配置文件(xml):appwidget providerinfo
创建AppWidgetProvider并覆写对应的生命周期方法
注册AppWidgetProvider
AppWidgetProvider:
package org.crazyit.desktop; 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; /** * Description: * <br/>site: <a href="http://www.crazyit.org">crazyit.org</a> * <br/>Copyright (C), 2001-2014, Yeeku.H.Lee * <br/>This program is protected by copyright laws. * <br/>Program Name: * <br/>Date: * @author Yeeku.H.Lee kongyeeku@163.com * @version 1.0 */ public class LedClock extends AppWidgetProvider { private Timer timer = new Timer(); private AppWidgetManager appWidgetManager; private Context context; // 将0~9的液晶数字图片定义成数组 private int[] digits = new int[] { R.drawable.su01, R.drawable.su02, R.drawable.su03, R.drawable.su04, R.drawable.su05, R.drawable.su06, R.drawable.su07, R.drawable.su08, R.drawable.su09, R.drawable.su10, }; // 将显示小时、分钟、秒钟的ImageView定义成数组 private int[] digitViews = new int[] { R.id.img01, R.id.img02, R.id.img04, R.id.img05, R.id.img07, R.id.img08 }; @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { System.out.println("--onUpdate--"); this.appWidgetManager = appWidgetManager; this.context = context; // 定义计时器 timer = new Timer(); // 启动周期性调度 timer.schedule(new TimerTask() { 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.main); // 定义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, LedClock.class); // 调用AppWidgetManager将remoteViews添加到ComponentName中 appWidgetManager.updateAppWidget(componentName, views); } super.handleMessage(msg); } }; }
<application android:icon="@drawable/ic_launcher" android:label="@string/app_name"> <receiver android:name=".LedClock" 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/my_clock" /> </receiver> </application>
xml配置文件:
<?xml version="1.0" encoding="utf-8"?> <!-- 指定该桌面组件的基本配置信息: minWidth:桌面控件的最小宽度。 minWidth:桌面控件的最小高度。 updatePeriodMillis:更新频率 initialLayout:初始时显示的布局 --> <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" android:minWidth="224px" android:minHeight="30px" android:updatePeriodMillis="1000" android:initialLayout="@layout/main"/>
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="fill_parent" > <!-- 定义5个ImageView来显示液晶数字 --> <ImageView android:id="@+id/img01" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <ImageView android:id="@+id/img02" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <ImageView android:id="@+id/img03" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/su00" /> <ImageView android:id="@+id/img04" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <ImageView android:id="@+id/img05" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <ImageView android:id="@+id/img06" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/su00" /> <ImageView android:id="@+id/img07" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <ImageView android:id="@+id/img08" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout>