What is App Widget?
在手機桌面上放置的控件,即Android的桌面組件
AppWidgetProviderInfo
extends Object
implements Parcelable
Describes the meta data for an installed AppWidget provider. The fields in this class correspond to the fields in the <appwidget-provider> xml tag.
AppWidgetProvider
AppWidgetProvider
extends BroadcastReceiver
A convenience class to aid in implementing an AppWidget provider. Everything you can do with AppWidgetProvider, you can do with a regularBroadcastReceiver. AppWidgetProvider merely parses the relevant fields out of the Intent that is received in onReceive(Context,Intent), and calls hook methods with the received extras.
① 在res文件夾下創建一個xml文件夾,裏面創建一個xml文件(這裏創建了一個test_appwidget_info.xml文件)用於提供元數據:
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" android:minWidth="200dp" android:minHeight="80dp" android:updatePeriodMillis="10000" android:initialLayout="@layout/test_appwidget" > </appwidget-provider>
其中的test_appwidget爲App Widget的佈局文件,在第二步創建。
② 創建App Widget的佈局文件test_appwidget.xml:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:id="@+id/widgetId" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="This is an AppWidget" android:background="#000" /> </LinearLayout>
③ 創建一個類繼承AppWidgetProvider並覆蓋裏面的幾個常用的方法:
onDisabled(Context context) 最後一個App Widget實例刪除後調用此方法
onEnabled(Context context) App WIdget實例第一次被創建是調用此方法
onReceive(Context context, Intent intent) 接收廣播事件
onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) 到達指定更新時間或用戶向桌面添加了App Widget時調用此方法
import android.appwidget.AppWidgetManager; import android.appwidget.AppWidgetProvider; import android.content.Context; public class TestAppWidgetProvider extends AppWidgetProvider{ @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { System.out.println("onUpdate"); super.onUpdate(context, appWidgetManager, appWidgetIds); } @Override public void onDeleted(Context context, int[] appWidgetIds) { System.out.println("onDeleted"); super.onDeleted(context, appWidgetIds); } @Override public void onDisabled(Context context) { System.out.println("onDisabled"); super.onDisabled(context); } @Override public void onEnabled(Context context) { System.out.println("onEnabled"); super.onEnabled(context); } }
④ 在AndroidManifest.xml文件中聲明一個receiver,注意intent和meta-data子標籤的設置:
<receiver android:name=".TestAppWidgetProvider"> <intent-filter> <action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> </intent-filter> <meta-data android:name="android.appwidget.provider" android:resource="@xml/test_appwidget_info" /> </receiver>
PendingIntent
PendingIntent
extends Object
implements Parcelable
A description of an Intent and target action to perform with it. Instances of this class are created with getActivity(Context, int, Intent, int),getBroadcast(Context, int, Intent, int), getService(Context, int, Intent, int); the returned object can be handed to other applications so that they can perform the action you described on your behalf at a later time.
RemoteViews
RemoteViews
extends Object
implements Parcelable LayoutInflater.Filter
A class that describes a view hierarchy that can be displayed in another process. The hierarchy is inflated from a layout resource file, and this class provides some basic operations for modifying the content of the inflated hierarchy.
創建PendingIntent的基本方法:
getBroadcast(Context context, int requestCode, Intent intent, int flags)
getService(Context context, int requestCode, Intent intent, int flags)
在創建一個簡單的App Widget的基本步驟基礎之上進行一下操作:
① 在test_appwidget.xml文件中添加一個按鈕
<Button android:id="@+id/widgetButtonId" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="click me?" />
② 通過RemoteViews在TestAppWidgetProvider的onUpdate()方法中爲Botton綁定監聽器
@Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { for (int i = 0; i < appWidgetIds.length; i++) { //這裏TargetActivity爲Intent跳轉到的Activity,這個Activity類需要另外編寫,在第三步創建 Intent intent = new Intent(context,TargetActivity.class); PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0); RemoteViews remoteViews = new RemoteViews(context.getPackageName(),R.layout.test_appwidget); //PendingIntent爲事件觸發是所要執行的PendingIntent remoteViews.setOnClickPendingIntent(R.id.widgetButtonId, pendingIntent); appWidgetManager.updateAppWidget(appWidgetIds[i], remoteViews); } super.onUpdate(context, appWidgetManager, appWidgetIds); }
③ 創建一個TargetActivity用作Botton的跳轉到的Activity
在創建一個簡單的App Widget的基本步驟基礎之上進行一下操作:
1、 在AndroidManifest.xml文件中爲TestAppWidgetProvider註冊新的intent
<receiver android:name=".TestAppWidgetProvider"> <intent-filter> <action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> </intent-filter> <intent-filter> <action android:name="com.test.UPDATE_APP_WIDGET"/> </intent-filter> <meta-data android:name="android.appwidget.provider" android:resource="@xml/test_appwidget_info" /> </receiver>
2、 在TestAppWidgetProvider中定義一個常量:
private static final String UPDATE_ACTION = "com.test.UPDATE_APP_WIDGET";
3、 在TestAppWidgetProvider的onUpdate()方法中使用getBroadcast()方法創建一個PendingIntent;併爲AppWidget當中的控件註冊監聽器
@Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { Intent intent = new Intent(); intent.setAction(UPDATE_ACTION); PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0); RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.test_appwidget); remoteViews.setOnClickPendingIntent(R.id.widgetButtonId, pendingIntent); appWidgetManager.updateAppWidget(appWidgetIds, remoteViews); }
4、 在onReceive()方法中接收所需要的廣播:
public void onReceive(Context context, Intent intent) { super.onReceive(context, intent); String action = intent.getAction(); if (UPDATE_ACTION.equals(action)) { System.out.println(UPDATE_ACTION); } }
@Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (UPDATE_ACTION.equals(action)) { RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.test_appwidget); remoteViews.setTextViewText(R.id.widgetTextId, "change"); AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context); //區分:RemoteViews代表App Widget中的所有空間,而ComponentName代表整個App Widget對象 ComponentName componentName = new ComponentName(context,ExampleAppWidgetProvider.class); appWidgetManager.updateAppWidget(componentName, remoteViews); } else { super.onReceive(context, intent); } }