AppWidgetProvider使用介绍

来源:互联网 发布:淘宝代练那家店好 编辑:程序博客网 时间:2024/05/19 12:27

一 介绍

AppWidgetProvider是android中提供的用于实现桌面小工具的类,其本质是一个广播,即BroadcastReceiver。下面是类的继承关系。


所以,在实际的使用中,把AppWidgetProvider当成一个BroadcastReceiver就可以了,这样许多功能就很好理解了。

二 开发一个桌面小工具的步骤

1 定义小工具界面:在res/layout/下新建一个xml文件,名为widget.xml,名称和内容可以自定义,看你的小工具要做成什么样子。

[html] view plaincopy在CODE上查看代码片派生到我的代码片
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="fill_parent"  
  4.     android:layout_height="fill_parent" >  
  5.   
  6.     <ImageView  
  7.         android:id="@+id/imageView1"  
  8.         android:layout_width="wrap_content"  
  9.         android:layout_height="wrap_content"  
  10.         android:layout_alignParentLeft="true"  
  11.         android:layout_alignParentTop="true"  
  12.         android:src="@drawable/clear_cover" />  
  13.   
  14. </RelativeLayout>  


2 定义小工具配置信息:在res/xml/下新建appwidget_provider_info.xml,名称随意选,添加如下内容

[html] view plaincopy在CODE上查看代码片派生到我的代码片
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:initialLayout="@layout/widget"  
  4.     android:minHeight="84dp"  
  5.     android:minWidth="84dp"  
  6.     android:updatePeriodMillis="86400000" >  
  7.   
  8. </appwidget-provider>  
上面几个参数意义很明确,initialLayout就是指小工具所使用的初始化布局,minHeight和minWidth定义小工具的最小尺寸,updatePeriodMillis定义了小工具的自动更新周期,毫秒为单位,每隔一个周期,小工具的自动更新就会触发。

3 定义小工具类,继承AppWidgetProvider:

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. public class MyAppWidgetProvider extends AppWidgetProvider {  
  2.   
  3.     public static final String TAG = "MyAppWidgetProvider";  
  4.     public static final String CLICK_ACTION = "com.example.action.CLICK";  
  5.     private static RemoteViews mRemoteViews;  
  6.   
  7.     /** 
  8.      * 每删除一次窗口小部件就调用一次 
  9.      */  
  10.     @Override  
  11.     public void onDeleted(Context context, int[] appWidgetIds) {  
  12.         super.onDeleted(context, appWidgetIds);  
  13.         Log.i(TAG, "onDeleted");  
  14.     }  
  15.   
  16.     /** 
  17.      * 当最后一个该窗口小部件删除时调用该方法,注意是最后一个 
  18.      */  
  19.     @Override  
  20.     public void onDisabled(Context context) {  
  21.         super.onDisabled(context);  
  22.         Log.i(TAG, "onDisabled");  
  23.     }  
  24.   
  25.     /** 
  26.      * 当该窗口小部件第一次添加到桌面时调用该方法,可添加多次但只第一次调用 
  27.      */  
  28.     @Override  
  29.     public void onEnabled(Context context) {  
  30.         super.onEnabled(context);  
  31.         Log.i(TAG, "onEnabled");  
  32.     }  
  33.   
  34.     /** 
  35.      * 接收窗口小部件点击时发送的广播 
  36.      */  
  37.     @Override  
  38.     public void onReceive(final Context context, Intent intent) {  
  39.         super.onReceive(context, intent);  
  40.         Log.i(TAG, "onReceive : action = " + intent.getAction());  
  41.   
  42.         //这里判断是自己的action,做自己的事情,比如小工具被点击了要干啥,这里是做来一个动画效果  
  43.         if (intent.getAction().equals(CLICK_ACTION)) {  
  44.             Toast.makeText(context, "clicked it", Toast.LENGTH_SHORT).show();  
  45.               
  46.             new Thread(new Runnable() {  
  47.                 @Override  
  48.                 public void run() {  
  49.                     Bitmap srcbBitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.clear_fan);  
  50.                     for (int i = 0; i < 20; i++) {  
  51.                         float degree = (i * 90)%360;  
  52.                         mRemoteViews.setImageViewBitmap(R.id.imageView1, rotateBitmap(context, srcbBitmap, degree));  
  53.                         Intent intentClick = new Intent();  
  54.                         intentClick.setAction(CLICK_ACTION);  
  55.                         PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intentClick, 0);  
  56.                         mRemoteViews.setOnClickPendingIntent(R.id.imageView1, pendingIntent);  
  57.                         AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);  
  58.                         appWidgetManager.updateAppWidget(  
  59.                                 new ComponentName(context, MyAppWidgetProvider.class), mRemoteViews);  
  60.                         try {  
  61.                             Thread.sleep(100);  
  62.                         } catch (InterruptedException e) {  
  63.                             e.printStackTrace();  
  64.                         }  
  65.                     }  
  66.                       
  67.                 }  
  68.             }).start();  
  69.               
  70.         }  
  71.           
  72.     }  
  73.   
  74.     /** 
  75.      * 每次窗口小部件被点击更新都调用一次该方法 
  76.      */  
  77.     @Override  
  78.     public void onUpdate(Context context, AppWidgetManager appWidgetManager,  
  79.             int[] appWidgetIds) {  
  80.         super.onUpdate(context, appWidgetManager, appWidgetIds);  
  81.         Log.i(TAG, "onUpdate");  
  82.   
  83.         final int counter = appWidgetIds.length;  
  84.         Log.i(TAG, "counter = " + counter);  
  85.         for (int i = 0; i < counter; i++) {  
  86.             int appWidgetId = appWidgetIds[i];  
  87.             onWidgetUpdate(context, appWidgetManager, appWidgetId);  
  88.         }  
  89.   
  90.     }  
  91.   
  92.     /** 
  93.      * 窗口小部件更新 
  94.      *  
  95.      * @param context 
  96.      * @param appWidgeManger 
  97.      * @param appWidgetId 
  98.      */  
  99.     private void onWidgetUpdate(Context context,  
  100.             AppWidgetManager appWidgeManger, int appWidgetId) {  
  101.   
  102.         Log.i(TAG, "appWidgetId = " + appWidgetId);  
  103.         mRemoteViews = new RemoteViews(context.getPackageName(), R.layout.widget);  
  104.   
  105.         // "窗口小部件"点击事件发送的Intent广播  
  106.         Intent intentClick = new Intent();  
  107.         intentClick.setAction(CLICK_ACTION);  
  108.         PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intentClick, 0);  
  109.         mRemoteViews.setOnClickPendingIntent(R.id.imageView1, pendingIntent);  
  110.         appWidgeManger.updateAppWidget(appWidgetId, mRemoteViews);  
  111.     }  
  112.   
  113.     private Bitmap rotateBitmap(Context context, Bitmap srcbBitmap, float degree) {  
  114.         Matrix matrix = new Matrix();  
  115.         matrix.reset();  
  116.         matrix.setRotate(degree);  
  117.         Bitmap tmpBitmap = Bitmap.createBitmap(srcbBitmap, 00, srcbBitmap.getWidth(),  
  118.                 srcbBitmap.getHeight(), matrix, true);  
  119.         return tmpBitmap;  
  120.     }  
  121.   
  122. }  

4 最后一步,在AndroidManifest.xml中声明小工具类:

[html] view plaincopy在CODE上查看代码片派生到我的代码片
  1. <receiver  
  2.     android:name=".MyAppWidgetProvider"  
  3.     android:icon="@drawable/df_fan_slow" >  
  4.     <meta-data  
  5.         android:name="android.appwidget.provider"  
  6.         android:resource="@xml/appwidget_provider_info" >  
  7.     </meta-data>  
  8.   
  9.     <intent-filter>  
  10.         <action android:name="com.example.action.CLICK" />  
  11.         <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />  
  12.     </intent-filter>  
  13. </receiver>  
说明:根据我调研的结果,大家都说android.appwidget.action.APPWIDGET_UPDATE是必须要提供的,我试了下,如果不加,就无法出现在手机小工具列表中。其他action可以根据需要自行添加。

其中AppWidgetProvider中的几个回调方法:onEnabled,onDisabled,onDeleted,onUpdated会自动被其onReceive方法在合适的时间调用,确切来说是,当广播到来以后,AppWidgetProvider会自动根据广播的action通过onReceive方法来自动派发广播,也就是调用上述几个方法。android源码里说的很清楚:

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. // BEGIN_INCLUDE(onReceive)  
  2. public void onReceive(Context context, Intent intent) {  
  3.     // Protect against rogue update broadcasts (not really a security issue,  
  4.     // just filter bad broacasts out so subclasses are less likely to crash).  
  5.     String action = intent.getAction();  
  6.     if (AppWidgetManager.ACTION_APPWIDGET_UPDATE.equals(action)) {  
  7.         Bundle extras = intent.getExtras();  
  8.         if (extras != null) {  
  9.             int[] appWidgetIds = extras.getIntArray(AppWidgetManager.EXTRA_APPWIDGET_IDS);  
  10.             if (appWidgetIds != null && appWidgetIds.length > 0) {  
  11.                 this.onUpdate(context, AppWidgetManager.getInstance(context), appWidgetIds);  
  12.             }  
  13.         }  
  14.     }  
  15.     else if (AppWidgetManager.ACTION_APPWIDGET_DELETED.equals(action)) {  
  16.         Bundle extras = intent.getExtras();  
  17.         if (extras != null && extras.containsKey(AppWidgetManager.EXTRA_APPWIDGET_ID)) {  
  18.             final int appWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID);  
  19.             this.onDeleted(context, new int[] { appWidgetId });  
  20.         }  
  21.     }  
  22.     else if (AppWidgetManager.ACTION_APPWIDGET_OPTIONS_CHANGED.equals(action)) {  
  23.         Bundle extras = intent.getExtras();  
  24.         if (extras != null && extras.containsKey(AppWidgetManager.EXTRA_APPWIDGET_ID)  
  25.                 && extras.containsKey(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS)) {  
  26.             int appWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID);  
  27.             Bundle widgetExtras = extras.getBundle(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS);  
  28.             this.onAppWidgetOptionsChanged(context, AppWidgetManager.getInstance(context),  
  29.                     appWidgetId, widgetExtras);  
  30.         }  
  31.     }  
  32.     else if (AppWidgetManager.ACTION_APPWIDGET_ENABLED.equals(action)) {  
  33.         this.onEnabled(context);  
  34.     }  
  35.     else if (AppWidgetManager.ACTION_APPWIDGET_DISABLED.equals(action)) {  
  36.         this.onDisabled(context);  
  37.     }  
  38. }  
  39. // END_INCLUDE(onReceive)  
0 0