桌面控件是經過 Broadcast 的形式來進行控制的,所以每一個桌面控件都對應於一個BroadcastReceiver。爲了簡化桌面控件的開發,Android 系統提供了一個 AppWidgetProvider類 , 它 就 是 BroadcastReceiver 的 子 類 , 也 就 是 說 開 發 者 開 發 桌 面 控 件 只 要 繼 承
AppWidgetProvider 類便可。java
爲了開發桌面控件,開發者只要開發一個繼承 AppWidgetProvider 的子類,並重寫AppWidgetProvider 不一樣狀態的生命週期方法便可。AppWidgetProvider 裏提供以下 4 個不一樣的生命週期方法。android
通常來講,開發桌面控件只須要定義一個 AppWidgetProvider 的子類,並重寫它的onUpdate()方法便可,重寫該方法按以下步驟進行。git
以下代碼簡單的將一張圖片做爲部件放到桌面上:數組
public class DesktopApp extends AppWidgetProvider { @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { // 加載指定界面佈局文件,建立RemoteViews對象 RemoteViews remoteViews = new RemoteViews( context.getPackageName(), R.layout.main); //① // 爲show ImageView設置圖片 remoteViews.setImageViewResource(R.id.show , R.drawable.logo); //② // 將AppWidgetProvider子類實例包裝成ComponentName對象 ComponentName componentName = new ComponentName( context, DesktopApp.class); //③ // 調用AppWidgetManager將remoteViews添加到ComponentName中 appWidgetManager.updateAppWidget(componentName , remoteViews); //④ } }
爲了實現一個液晶時鐘的桌面組件,開發者須要在程序界面上定義 8 個 ImageView,其中 6 個 ImageView 用於顯示小時、分鐘、秒鐘的數字,另外兩個 ImageView 用於顯示小時、分鐘、秒鐘之間的冒號。
爲了讓桌面組件實時地顯示當前時間,程序須要每隔 1 秒更新一次程序界面上的 6 個ImageView,讓它們顯示當前小時、分鐘、秒鐘的數字便可。app
LED電子時鐘桌面部件依賴以下代碼實現:ide
main.xml函數
<?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>
Manifest.xml佈局
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="org.crazyit.desktop" android:versionCode="1" android:versionName="1.0"> <uses-sdk android:minSdkVersion="10" android:targetSdkVersion="17" /> <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> </manifest>
my_clock.xmlthis
<?xml version="1.0" encoding="utf-8"?> <!-- 指定該桌面組件的基本配置信息: minWidth:桌面控件的最小寬度。 minWidth:桌面控件的最小高度。 updatePeriodMillis:更新頻率 initialLayout:初始時顯示的佈局 --> <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" android:minWidth="800px" android:minHeight="30px" android:updatePeriodMillis="1000" android:initialLayout="@layout/main"/>
LedClock.java編碼
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個數字字符轉換爲對應的數字,charAt函數返回的是ASCII編碼,1的ASCII編碼是49,因此須要減去偏移量48。 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); } }; }
效果: