一 介绍
AppWidgetProvider是android中提供的用于实现桌面小工具的类,其本质是一个广播,即BroadcastReceiver。下面是类的继承关系。
所以,在实际的使用中,把AppWidgetProvider当成一个BroadcastReceiver就可以了,这样许多功能就很好理解了。
二 开发一个桌面小工具的步骤
1 定义小工具界面:在res/layout/下新建一个xml文件,名为widget.xml,名称和内容可以自定义,看你的小工具要做成什么样子。
- <?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>
2 定义小工具配置信息:在res/xml/下新建appwidget_provider_info.xml,名称随意选,添加如下内容
- <?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>
3 定义小工具类,继承AppWidgetProvider:
- 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;
- }
- }
4 最后一步,在AndroidManifest.xml中声明小工具类:
- <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>
其中AppWidgetProvider中的几个回调方法:onEnabled,onDisabled,onDeleted,onUpdated会自动被其onReceive方法在合适的时间调用,确切来说是,当广播到来以后,AppWidgetProvider会自动根据广播的action通过onReceive方法来自动派发广播,也就是调用上述几个方法。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)