所謂案頭小控制項,就是指能直接顯示在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 };@Overridepublic void onUpdate(Context context, AppWidgetManager appWidgetManager,int[] appWidgetIds) {this.appWidgetManager = appWidgetManager;this.context = context;// 定義計時器timer = new Timer();// 啟動周期性調度timer.schedule(new TimerTask() {@Overridepublic 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" />