AppWidgetProvider使用介紹

一 介紹

AppWidgetProvider是android中提供的用於實現桌面小工具的類,其本質是一個廣播,即BroadcastReceiver。下面是類的繼承關係。
html


因此,在實際的使用中,把AppWidgetProvider當成一個BroadcastReceiver就能夠了,這樣許多功能就很好理解了。java

二 開發一個桌面小工具的步驟

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>
上面幾個參數意義很明確,initialLayout就是指小工具所使用的初始化佈局,minHeight和minWidth定義小工具的最小尺寸,updatePeriodMillis定義了小工具的自動更新週期,毫秒爲單位,每隔一個週期,小工具的自動更新就會觸發。

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>
說明:根據我調研的結果,你們都說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)
相關文章
相關標籤/搜索