«

AppWidgetProvider使用介绍

时间:2024-3-2 17:34     作者:韩俊     分类: Android


一 介绍

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


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

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

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

[html] view
plaincopy

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android&quot;
android:layout_width="fill_parent"
android:layout_height="fill_parent" >

&lt;ImageView  
    android:id=&quot;@&#43;id/imageView1&quot;  
    android:layout_width=&quot;wrap_content&quot;  
    android:layout_height=&quot;wrap_content&quot;  
    android:layout_alignParentLeft=&quot;true&quot;  
    android:layout_alignParentTop=&quot;true&quot;  
    android:src=&quot;@drawable/clear_cover&quot; /&gt;  

</RelativeLayout>


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

[html] view
plaincopy

<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android&quot;
android:initialLayout="@layout/widget"
android:minHeight="84dp"
android:minWidth="84dp"
android:updatePeriodMillis="86400000" >

</appwidget-provider>

上面几个参数意义很明确,initialLayout就是指小工具所使用的初始化布局,minHeight和minWidth定义小工具的最小尺寸,updatePeriodMillis定义了小工具的自动更新周期,毫秒为单位,每隔一个周期,小工具的自动更新就会触发。

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

[java] view
plaincopy

public class MyAppWidgetProvider extends AppWidgetProvider {

public static final String TAG = &quot;MyAppWidgetProvider&quot;;  
public static final String CLICK_ACTION = &quot;com.example.action.CLICK&quot;;  
private static RemoteViews mRemoteViews;  

/** 
 * 每删除一次窗口小部件就调用一次 
 */  
@Override  
public void onDeleted(Context context, int[] appWidgetIds) {  
    super.onDeleted(context, appWidgetIds);  
    Log.i(TAG, &quot;onDeleted&quot;);  
}  

/** 
 * 当最后一个该窗口小部件删除时调用该方法,注意是最后一个 
 */  
@Override  
public void onDisabled(Context context) {  
    super.onDisabled(context);  
    Log.i(TAG, &quot;onDisabled&quot;);  
}  

/** 
 * 当该窗口小部件第一次添加到桌面时调用该方法,可添加多次但只第一次调用 
 */  
@Override  
public void onEnabled(Context context) {  
    super.onEnabled(context);  
    Log.i(TAG, &quot;onEnabled&quot;);  
}  

/** 
 * 接收窗口小部件点击时发送的广播 
 */  
@Override  
public void onReceive(final Context context, Intent intent) {  
    super.onReceive(context, intent);  
    Log.i(TAG, &quot;onReceive : action = &quot; &#43; intent.getAction());  

    //这里判断是自己的action,做自己的事情,比如小工具被点击了要干啥,这里是做来一个动画效果  
    if (intent.getAction().equals(CLICK_ACTION)) {  
        Toast.makeText(context, &quot;clicked it&quot;, 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 &lt; 20; i&#43;&#43;) {  
                    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, &quot;onUpdate&quot;);  

    final int counter = appWidgetIds.length;  
    Log.i(TAG, &quot;counter = &quot; &#43; counter);  
    for (int i = 0; i &lt; counter; i&#43;&#43;) {  
        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, &quot;appWidgetId = &quot; &#43; appWidgetId);  
    mRemoteViews = new RemoteViews(context.getPackageName(), R.layout.widget);  

    // &quot;窗口小部件&quot;点击事件发送的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中声明小工具类:

[html] view
plaincopy

<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>

&lt;intent-filter&gt;  
    &lt;action android:name=&quot;com.example.action.CLICK&quot; /&gt;  
    &lt;action android:name=&quot;android.appwidget.action.APPWIDGET_UPDATE&quot; /&gt;  
&lt;/intent-filter&gt;  

</receiver>

说明:根据我调研的结果,大家都说android.appwidget.action.APPWIDGET_UPDATE是必须要提供的,我试了下,如果不加,就无法出现在手机小工具列表中。其他action可以根据需要自行添加。

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

[java] view
plaincopy

// 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)

标签: android

热门推荐