定義
Android中提供了AppWidgetProvider類為實作桌面小部件,AppWidgetProvider繼承了BroadcastReceiver,是以它本質上是一個廣播。
常用方法
AppWidgetProvider類有幾個常用的重要方法,它們會自動地在廣播接收後的onReceive方法裡在特定的條件下被調用,這些方法有:
onEnable 當小部件第一次添加到桌面時調用該方法,小部件可以添加多次但該方法隻會在第一次添加時調用。
onUpdate 小部件被添加時或每次自動更新時都會調用一次該方法。
onDeleted 每删除一次桌面小部件就調用一次。
onDisabled 當最後一個該類型的桌面小部件被删除時調用該方法。
示例
1、定義小部件界面
建立XML檔案:res/layout/app_widget.xml:
<?xml version="1.0"encoding="utf-8"?>
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical" >
<ImageView
android:id="@+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/sunny" />
<TextView
android:id="@+id/textView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textSize="30dp"
android:text="天晴"/>
</LinearLayout>
2、定義小部件配置資訊
建立XML檔案:res/xml/appwidget_provider_info.xml:
<?xml version="1.0"encoding="utf-8"?>
<appwidget-providerxmlns:android="http://schemas.android.com/apk/res/android"
android:initialLayout="@layout/app_widget" // 初始化布局檔案
android:minHeight="230dp" // 最小尺寸
android:minWidth="225dp" // 最小尺寸
android:updatePeriodMillis="10000" > // 自動更新周期(SDK1.6及以上版本,小于30分鐘的話,系統自動當30分鐘)
</appwidget-provider>
3、定義小部件實作類
public class AppWidgetProvider extends android.appwidget.AppWidgetProvider {
public static final String CLICK_ACTION ="com.example.action.CLICK";
private int[] mImageIds = { R.drawable.sunny, R.drawable.rain,R.drawable.cloudy };
private String[] mTexts = { "天晴", "小雨","多雲" };
public AppWidgetProvider() {
super();
}
@Override
public void onReceive(final Context context, Intent intent) {
super.onReceive(context, intent);
if (intent.getAction().equals(CLICK_ACTION)) {
AppWidgetManager appWidgetManager =AppWidgetManager.getInstance(context);
onWidgetUpdate(context, appWidgetManager, -1, new ComponentName(context,AppWidgetProvider.class));
}
}
@Override
public void onEnabled(Context context) {
super.onEnabled(context);
}
/**
* 每次視窗小部件被點選更新都調用一次該方法
*/
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
super.onUpdate(context, appWidgetManager, appWidgetIds);
final int counter = appWidgetIds.length;
for (int i = 0; i < counter; i++) {
int appWidgetId = appWidgetIds[i];
onWidgetUpdate(context, appWidgetManager, appWidgetId, null);
}
}
@Override
public void onDeleted(Context context, int[]appWidgetIds) {
super.onDeleted(context, appWidgetIds);
}
@Override
public void onDisabled(Context context) {
super.onDisabled(context);
}
/**
* 小部件更新
*
* @param context
* @param appWidgeManger
* @param appWidgetId
* @param provider
*/
private void onWidgetUpdate(Context context, AppWidgetManager appWidgeManger, int appWidgetId, ComponentName provider) {
// 生成0~2的随機數,用于随機轉換天氣
Random random = new Random();
int index = random.nextInt(3);
// 用于圖示點選的意圖
Intent intentBroadcast = new Intent();
intentBroadcast.setAction(CLICK_ACTION);
PendingIntent pendingIntentBroadcast = PendingIntent.getBroadcast(context,0, intentBroadcast, PendingIntent.FLAG_UPDATE_CURRENT);
// 用于文字點選的意圖
Intent intentActivity = new Intent(context, MainActivity.class);
PendingIntent pendingIntentActivity = PendingIntent.getActivity(context,0, intentActivity, PendingIntent.FLAG_UPDATE_CURRENT);
// 定義RemoteViews布局
RemoteViews remoteViews = new RemoteViews(context.getPackageName(),R.layout.app_widget);
remoteViews.setImageViewBitmap(R.id.imageView1,BitmapFactory.decodeResource(context.getResources(), mImageIds[index]));
remoteViews.setTextViewText(R.id.textView1, mTexts[index]);
remoteViews.setOnClickPendingIntent(R.id.imageView1,pendingIntentBroadcast);
remoteViews.setOnClickPendingIntent(R.id.textView1,pendingIntentActivity);
if (appWidgetId == -1 && remoteViews != null) {
appWidgeManger.updateAppWidget(provider, remoteViews);
} else {
appWidgeManger.updateAppWidget(appWidgetId,remoteViews);
}
}
}
4、因為是廣播,是以最後别忘了在AndroidManifest.xml中聲明小部件
<receiver android:name=".AppWidgetProvider" >
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/appwidget_provider_info" >
</meta-data>
<intent-filter>
<action android:name="com.example.action.CLICK" />
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
</receiver>
效果
說明
1、上面示例小部件做了一個示範和當單擊圖檔會随機切換一種天氣展示,當單擊文字時會打開MainActivity
2、當小部件單擊後切換天氣展示則是通過更新RemoteView來實作的
3、AndroidManifers.xml中有兩個Action,其中第一個Action用于識别小部件的單擊行為,而第二個Action是系統的規範,作為小部件的辨別而必須存在
4、SDK1.6及以上版本,自動更新最小間隔為30分鐘。是以如果您APP需要高頻更新小部件,例如像時鐘小部件那樣,一般需要一分種重新整理一次的話,則需要自己通過服務來重新整理時間的顯示