AppWidgetProvider是android中提供的用於實現桌面小工具的類,其本質是一個廣播,即BroadcastReceiver。下面是類的繼承關係。
html
因此,在實際的使用中,把AppWidgetProvider當成一個BroadcastReceiver就能夠了,這樣許多功能就很好理解了。java
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" > <ImageView android:id="@+id/imageView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:src="@drawable/clear_cover" /> </RelativeLayout>
<?xml version="1.0" encoding="utf-8"?> <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" android:initialLayout="@layout/widget" android:minHeight="84dp" android:minWidth="84dp" android:updatePeriodMillis="86400000" > </appwidget-provider>上面幾個參數意義很明確,initialLayout就是指小工具所使用的初始化佈局,minHeight和minWidth定義小工具的最小尺寸,updatePeriodMillis定義了小工具的自動更新週期,毫秒爲單位,每隔一個週期,小工具的自動更新就會觸發。
public class MyAppWidgetProvider extends AppWidgetProvider { public static final String TAG = "MyAppWidgetProvider"; public static final String CLICK_ACTION = "com.example.action.CLICK"; private static RemoteViews mRemoteViews; /** * 每刪除一次窗口小部件就調用一次 */ @Override public void onDeleted(Context context, int[] appWidgetIds) { super.onDeleted(context, appWidgetIds); Log.i(TAG, "onDeleted"); } /** * 當最後一個該窗口小部件刪除時調用該方法,注意是最後一個 */ @Override public void onDisabled(Context context) { super.onDisabled(context); Log.i(TAG, "onDisabled"); } /** * 當該窗口小部件第一次添加到桌面時調用該方法,可添加屢次但只第一次調用 */ @Override public void onEnabled(Context context) { super.onEnabled(context); Log.i(TAG, "onEnabled"); } /** * 接收窗口小部件點擊時發送的廣播 */ @Override public void onReceive(final Context context, Intent intent) { super.onReceive(context, intent); Log.i(TAG, "onReceive : action = " + intent.getAction()); //這裏判斷是本身的action,作本身的事情,好比小工具被點擊了要幹啥,這裏是作來一個動畫效果 if (intent.getAction().equals(CLICK_ACTION)) { Toast.makeText(context, "clicked it", Toast.LENGTH_SHORT).show(); new Thread(new Runnable() { @Override public void run() { Bitmap srcbBitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.clear_fan); for (int i = 0; i < 20; i++) { float degree = (i * 90)%360; mRemoteViews.setImageViewBitmap(R.id.imageView1, rotateBitmap(context, srcbBitmap, degree)); Intent intentClick = new Intent(); intentClick.setAction(CLICK_ACTION); PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intentClick, 0); mRemoteViews.setOnClickPendingIntent(R.id.imageView1, pendingIntent); AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context); appWidgetManager.updateAppWidget( new ComponentName(context, MyAppWidgetProvider.class), mRemoteViews); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); } } /** * 每次窗口小部件被點擊更新都調用一次該方法 */ @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { super.onUpdate(context, appWidgetManager, appWidgetIds); Log.i(TAG, "onUpdate"); final int counter = appWidgetIds.length; Log.i(TAG, "counter = " + counter); for (int i = 0; i < counter; i++) { int appWidgetId = appWidgetIds[i]; onWidgetUpdate(context, appWidgetManager, appWidgetId); } } /** * 窗口小部件更新 * * @param context * @param appWidgeManger * @param appWidgetId */ private void onWidgetUpdate(Context context, AppWidgetManager appWidgeManger, int appWidgetId) { Log.i(TAG, "appWidgetId = " + appWidgetId); mRemoteViews = new RemoteViews(context.getPackageName(), R.layout.widget); // "窗口小部件"點擊事件發送的Intent廣播 Intent intentClick = new Intent(); intentClick.setAction(CLICK_ACTION); PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intentClick, 0); mRemoteViews.setOnClickPendingIntent(R.id.imageView1, pendingIntent); appWidgeManger.updateAppWidget(appWidgetId, mRemoteViews); } private Bitmap rotateBitmap(Context context, Bitmap srcbBitmap, float degree) { Matrix matrix = new Matrix(); matrix.reset(); matrix.setRotate(degree); Bitmap tmpBitmap = Bitmap.createBitmap(srcbBitmap, 0, 0, srcbBitmap.getWidth(), srcbBitmap.getHeight(), matrix, true); return tmpBitmap; } }
<receiver android:name=".MyAppWidgetProvider" android:icon="@drawable/df_fan_slow" > <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>說明:根據我調研的結果,你們都說android.appwidget.action.APPWIDGET_UPDATE是必需要提供的,我試了下,若是不加,就沒法出如今手機小工具列表中。其餘action能夠根據須要自行添加。
其中AppWidgetProvider中的幾個回調方法:onEnabled,onDisabled,onDeleted,onUpdated會自動被其onReceive方法在合適的時間調用,確切來講是,當廣播到來之後,AppWidgetProvider會自動根據廣播的action經過onReceive方法來自動派發廣播,也就是調用上述幾個方法。android源碼裏說的很清楚:android
// BEGIN_INCLUDE(onReceive) public void onReceive(Context context, Intent intent) { // Protect against rogue update broadcasts (not really a security issue, // just filter bad broacasts out so subclasses are less likely to crash). String action = intent.getAction(); if (AppWidgetManager.ACTION_APPWIDGET_UPDATE.equals(action)) { Bundle extras = intent.getExtras(); if (extras != null) { int[] appWidgetIds = extras.getIntArray(AppWidgetManager.EXTRA_APPWIDGET_IDS); if (appWidgetIds != null && appWidgetIds.length > 0) { this.onUpdate(context, AppWidgetManager.getInstance(context), appWidgetIds); } } } else if (AppWidgetManager.ACTION_APPWIDGET_DELETED.equals(action)) { Bundle extras = intent.getExtras(); if (extras != null && extras.containsKey(AppWidgetManager.EXTRA_APPWIDGET_ID)) { final int appWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID); this.onDeleted(context, new int[] { appWidgetId }); } } else if (AppWidgetManager.ACTION_APPWIDGET_OPTIONS_CHANGED.equals(action)) { Bundle extras = intent.getExtras(); if (extras != null && extras.containsKey(AppWidgetManager.EXTRA_APPWIDGET_ID) && extras.containsKey(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS)) { int appWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID); Bundle widgetExtras = extras.getBundle(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS); this.onAppWidgetOptionsChanged(context, AppWidgetManager.getInstance(context), appWidgetId, widgetExtras); } } else if (AppWidgetManager.ACTION_APPWIDGET_ENABLED.equals(action)) { this.onEnabled(context); } else if (AppWidgetManager.ACTION_APPWIDGET_DISABLED.equals(action)) { this.onDisabled(context); } } // END_INCLUDE(onReceive)