1. 程式人生 > >Android開發桌面外掛

Android開發桌面外掛

前提:公司應用需要開發外掛,奈何我實在沒有塊的開發經驗,查閱了一些資料,花了幾天時間,完成了外掛的開發。

開發桌面外掛需要了解AppWidgetProvider,RemoteViewsService,RemoteViewsFactory,appwidget-provider

外掛的更新主要是AppWidgetProvider,列表性的需要RemoteViewsService,RemoteViewsFactory,介面由appwidget-provider提供

首先是appwidget-provider,這個網上有很多的說明,我就不一一說了,我這裡主要用了

initialLayout:載入我們外掛的佈局

updatePeriodMillis:外掛的更新頻率

previewImage:外掛預覽圖片

configure:當 widget 建立時,會自動啟動該 Activity

然後是AppWidgetProvider

public class MyAppWidgetProvider extends AppWidgetProvider {

    /**
     * 當第1個 widget 的例項被建立時觸發。
     */
    @Override
    public void onEnabled(Context context) {
        super.onEnabled(context);

    }

    /**
     * 接收到任意廣播時觸發,並且會在上述的方法之前被呼叫。
     */
    @Override
    public void onReceive(Context context, Intent intent) {
        super.onReceive(context, intent);
        /**
         *  如果你的Widget要求並不是很特殊,一般情況下,在此接收廣播,即可處理相應事務,但在此就放棄該方法了。
         */
    }

    /**
     * 當 widget 更新時被執行。每次建立Widget,或者剛開機等情況下,都會被執行。
     */
    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        /**
         *  由於Widget本身不支援執行太過耗時的操作,所以,為了實現開機重新整理和每次新增的時候重新整理資料,開啟服務,
         *  讓資料在後臺下載,等下載完成之後,在進行更新Widget的操作。
         *
         */
        Intent intent = new Intent(context, MyService.class);
        intent.putExtra("appWidgetIds", appWidgetIds);
        context.startService(intent);
    }

    /**
     * 當 widget 被刪除時被觸發。
     */
    @Override
    public void onDeleted(Context context, int[] appWidgetIds) {
        super.onDeleted(context, appWidgetIds);
    }

    /**
     * 當最後1個 widget 的例項被刪除時觸發。
     */
    @Override
    public void onDisabled(Context context) {
        super.onDisabled(context);
    }
}
更新操作都在update中進行,

 @Override
    public void onReceive(Context context, Intent intent) {
        super.onReceive(context, intent);

            //將介面應用到外掛中
            AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
            int[] ids = appWidgetManager.getAppWidgetIds(new ComponentName(context, WidgetA.class));
            onUpdate(context, appWidgetManager, ids);
        

    }
在onreceive中最後加入這個三行程式碼,外部發出的update操作都會經過onreceive。

Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
Bundle extras = new Bundle();
intent.putExtras(extras);
sendBroadcast(intent);
其他檔案中使用該程式碼就會更新外掛。

如果你有在外掛中使用listview,gridview這類控制元件,就需要RemoteViewsService,RemoteViewsFactory進行資料更新,和adapter一樣

public class WidgetGridService extends RemoteViewsService {


    @Override
    public RemoteViewsFactory onGetViewFactory(Intent intent) {
        return new GridRemoteViewFactory(this, intent);
    }

    private class GridRemoteViewFactory implements RemoteViewsFactory {

        private Context context;
        private int appWidgetId;
        private List<WidgetEntity.NewslistBean> newslist = new ArrayList<>();

        public GridRemoteViewFactory(Context context, Intent intent) {
            this.context = context;
            this.appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
                    AppWidgetManager.INVALID_APPWIDGET_ID);
        }

        /**
         * 首次執行,初始化資料時執行onCreate();資料是從資料庫裡拿的。
         */
        @Override
        public void onCreate() {
            try {
                newslist = MyApplication.getMyApp().getDbUtils().findAll(WidgetEntity.NewslistBean.class);
            } catch (DbException e) {
                e.printStackTrace();
            }
        }

        /**
         * 當資料來源發生變化時,AppWidgetManager呼叫了 notifyAppWidgetViewDataChanged();方法時執行
         */
        @Override
        public void onDataSetChanged() {
            try {
                newslist = MyApplication.getMyApp().getDbUtils().findAll(WidgetEntity.NewslistBean.class);
            } catch (DbException e) {
                e.printStackTrace();
            }
        }

        /**
         * 銷燬資料來源
         */
        @Override
        public void onDestroy() {
            newslist.clear();
        }

        /**
         * 返回Gridview的Item條目數
         */
        @Override
        public int getCount() {
            return newslist.size();
        }

        /**
         * 給Gridview設定資料
         */
        @Override
        public RemoteViews getViewAt(int position) {
            RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.item_grid);
            if (newslist != null) {//item的xml檔案
                remoteViews.setTextViewText(R.id.item_text, newslistBean.getTitle());

                //給item設定響應事件
                Intent intent = new Intent();
                intent.putExtra("url", newslistBean.getUrl());
                remoteViews.setOnClickFillInIntent(R.id.item_widget, intent);
            }
            return remoteViews;
        }

        @Override
        public RemoteViews getLoadingView() {
            return null;
        }

        /**
         * 無特殊要求,返回的View型別數 ==1;
         */
        @Override
        public int getViewTypeCount() {
            return 1;
        }

        /**
         * 返回item的id
         */
        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public boolean hasStableIds() {
            return true;
        }

    }
}

然後在mainfest註冊改外掛

<receiver android:name=".MyAppWidgetProvider">
    <intent-filter>
        <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
    </intent-filter>
    <meta-data
        android:name="android.appwidget.provider"
        android:resource="@xml/widget_main" />
</receiver>

<service
            android:name=".WidgetGridService"
            android:exported="false"
            android:permission="android.permission.BIND_REMOTEVIEWS"/>

到這裡基本都已經完成了外掛的基本開發。具體的操作需要在開發中使用時根據自己的情況在進行處理。