Android開發指南-窗口小部件(App Widgets)

http://blog.csdn.net/iefreer/article/details/4626274# java


應用程序窗口小部件App Widgetsandroid

應用程序窗口小部件(Widget)是微小的應用程序視圖,能夠被嵌入到其它應用程序中(好比桌面)並接收週期性的更新。你能夠經過一個App Widget provider來發佈一個Widget。能夠容納其它App Widget的應用程序組件被稱爲App Widget宿主。下面的截屏顯示了一個音樂App Widget數據庫

  appwidget 

這篇文章描述瞭如何使用App Widget Provider發佈一個App Widget編程

基礎知識The Basics數組

爲了建立一個App Widget,你須要下面這些:app

AppWidgetProviderInfo 對象框架

描述一個App Widget元數據,好比App Widget的佈局,更新頻率,以及AppWidgetProvider 類。這應該在XML裏定義。ide

AppWidgetProvider 類的實現函數

定義基本方法以容許你編程來和App Widget鏈接,這基於廣播事件。經過它,當這個App Widget被更新,啓用,禁用和刪除的時候,你都將接收到廣播通知。oop

視圖佈局

爲這個App Widget定義初始佈局,在XML中。

另外,你能夠實現一個App Widget配置活動。這是一個可選的活動Activity,當用戶添加App Widget時加載並容許他在建立時來修改App Widget的設置。

下面的章節描述瞭如何創建這些組件:

在清單中聲明一個應用小部件

首先,在應用程序AndroidManifest.xml文件中聲明AppWidgetProvider 類,好比:

<receiver android:name="ExampleAppWidgetProvider" >

    <intent-filter>

        <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />

    </intent-filter>

    <meta-data android:name="android.appwidget.provider"

               android:resource="@xml/example_appwidget_info" />

</receiver>

<receiver>元素須要android:name屬性,它指定了App Widget使用的AppWidgetProvider 

<intent-filter> 元素必須包括一個含有android:name屬性的<action>元素。該元素指定AppWidgetProvider接受ACTION_APPWIDGET_UPDATE 廣播。這是惟一你必須顯式聲明的廣播。當須要的時候,AppWidgetManager 會自動發送全部其餘App Widget廣播給AppWidgetProvider

<meta-data> 元素指定了AppWidgetProviderInfo 資源並須要如下屬性:

·         android:name – 指定元數據名稱。

·         android:resource – 指定AppWidgetProviderInfo 資源路徑。

 

增長AppWidgetProviderInfo元數據

AppWidgetProviderInfo定義一個App Widget的基本特性,好比最小布局尺寸,初始佈局資源,刷新頻率,以及(可選的)建立時加載的一個配置活動。使用單獨的一個<appwidget-provider>元素在XML資源裏定義AppWidgetProviderInfo 對象並保存到項目的res/xml/目錄下。

好比:

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"

    android:minWidth="294dp" <!-- density-independent pixels -->

    android:minHeight="72dp"

    android:updatePeriodMillis="86400000" <!-- once per day -->

    android:initialLayout="@layout/example_appwidget"

    android:configure="com.example.android.ExampleAppWidgetConfigure" >

</appwidget-provider>

下面是<appwidget-provider>屬性的總結:

·         minWidth minHeight 屬性的值指定了這個App Widget佈局須要的最小區域。

缺省的App Widgets所在窗口的桌面位置基於有確切高度和寬度的單元網格。若是App Widget的最小長寬和這些網格單元的尺寸不匹配,那麼這個App Widget將收縮到最接近的單元尺寸。(參見App Widget Design Guidelines 以獲取更多關於桌面單元尺寸的信息)

由於桌面佈局方向(由此,單元的尺寸)能夠變化,按照拇指規則,你應該假設最壞狀況單元尺寸是74像素高和寬。不過,你必須從最後的尺寸中減去2以把像素計算過程當中產生的任何的整數舍入偏差考慮在內。要找到像素密度無關的最小寬度和高度,使用這個公式:
(number of cells * 74) - 2
遵循這個公式,你應該使用72dp爲每個單元高度,294dp爲四個單元寬度。

·         updatePerdiodMillis 屬性定義了App Widget框架調用onUpdate()方法來從AppWidgetProvider請求一次更新的頻度。實際更新時間並不那麼精確,並且咱們建議更新頻率越低越好-也許每小時不超過一次以節省電源。你也許還會容許用戶在配置中調整這個頻率-一些人可能想每15分鐘一次股票報價,或者一天只要四次。

·         initialLayout屬性指向定義App Widget佈局的資源。

·         configure屬性定義了Activity ,當用戶添加App Widget時啓動,覺得他或她配置App Widget特性。這是可選的(閱讀下面的Creating an App Widget Configuration Activity)。

參見AppWidgetProviderInfo 類以獲取更多能夠被<appwidget-provider>元素接受的屬性信息。

建立App Widget佈局

你必須在XML中爲你的App Widget定義一個初始佈局並保存到項目的res/layout/ 目錄下。你可使用以下所列的視圖對象來設計你的App Widget,可是在此以前,請先閱讀並理解App Widget Design Guidelines.

若是你熟悉在XML中聲明佈局,那麼建立這個App Widget佈局是很簡單的。可是,你必須意識到那個App Widget佈局是基於RemoteViews這並不支持全部類型的佈局或視圖小部件。

一個RemoteViews對象(以及,相應的,一個App Widget)能夠支持下面這個佈局類:

·         FrameLayout

·         LinearLayout

·         RelativeLayout

以及下面的小部件類:

·         AnalogClock

·         Button

·         Chronometer

·         ImageButton

·         ImageView

·         ProgressBar

·         TextView

不支持這些類的派生。

使用AppWidgetProvider

你必須經過在清單文件中使用<receiver>元素來聲明你的AppWidgetProvider 類實現爲一個廣播接收器(參見上面的Declaring an App Widget in the Manifest)。

AppWidgetProvider 類擴展BroadcastReceiver 爲一個簡便類來處理App Widget廣播。AppWidgetProvider只接收和這個App Widget相關的事件廣播,好比這個App Widget被更新,刪除,啓用,以及禁用。當這些廣播事件發生時,AppWidgetProvider 將接收到下面的方法調用:

onUpdate(Context, AppWidgetManager, int[])

這個方法調用來間隔性的更新App Widget,間隔時間用AppWidgetProviderInfo 裏的updatePeriodMillis屬性定義(參見添加AppWidgetProviderInfo元數據)。這個方法也會在用戶添加App Widget時被調用,所以它應該執行基礎的設置,好比爲視圖定義事件處理器並啓動一個臨時的服務Service若是須要的話。可是,若是你已經聲明瞭一個配置活動,這個方法在用戶添加App Widget時將不會被調用,而只在後續更新時被調用。配置活動應該在配置完成時負責執行第一次更新。(參見下面的建立一個App Widget配置活動Creating an App Widget Configuration Activity

onDeleted(Context, int[])

App Widget從宿主中刪除時被調用。

onEnabled(Context)

當一個App Widget實例第一次建立時被調用。好比,若是用戶添加兩個你的App Widget實例,只在第一次被調用。若是你須要打開一個新的數據庫或者執行其餘對於全部的App Widget實例只須要發生一次的設置,那麼這裏是完成這個工做的好地方。

onDisabled(Context)

當你的App Widget的最後一個實例被從宿主中刪除時被調用。你應該在onEnabled(Context)中作一些清理工做,好比刪除一個臨時的數據庫。

onReceive(Context, Intent)

這個接收到每一個廣播時都會被調用,並且在上面的回調函數以前。你一般不須要實現這個方法,由於缺省的AppWidgetProvider 實現過濾全部App Widget 廣播並恰當的調用上述方法。

注意: Android 1.5中, 有一個已知問題,onDeleted()方法在該調用時不被調用。爲了規避這個問題,你能夠像Group post中描述的那樣實現onReceive() 來接收這個onDeleted()回調。

最重要的AppWidgetProvider 回調函數是onUpdated() 由於它是在每一個App Widget添加進宿主時被調用的(除非你使用一個配置活動)。若是你的App Widget 要接受任何用戶交互事件,那麼你須要在這個回調函數中註冊事件處理器。若是你的App Widget不建立臨時文件或數據庫,或者執行其它須要清理的工做,那麼onUpdated() 多是你須要定義的惟一的回調函數。好比,若是你想要一個帶一個按鈕的App Widget,當點擊時啓動一個活動,你可使用下面的AppWidgetProvider實現:

public class ExampleAppWidgetProvider extends AppWidgetProvider {

 

    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {

        final int N = appWidgetIds.length;

 

        // Perform this loop procedure for each App Widget that belongs to this provider

        for (int i=0; i<N; i++) {

            int appWidgetId = appWidgetIds[i];

 

            // Create an Intent to launch ExampleActivity

            Intent intent = new Intent(context, ExampleActivity.class);

            PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);

 

            // Get the layout for the App Widget and attach an on-click listener to the button

            RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.appwidget_provider_layout);

            views.setOnClickPendingIntent(R.id.button, pendingIntent);

 

            // Tell the AppWidgetManager to perform an update on the current App Widget

            appWidgetManager.updateAppWidget(appWidgetId, views);

        }

    }

}

這個AppWidgetProvider 僅定義了onUpdated() 方法,爲了定義一個PendingIntent來啓動一個活動並使用setOnClickPendingIntent(int, PendingIntent)方法把它附着到這個App Widget的按鈕上。注意它包含了一個遍歷appWidgetIds中全部項的循環,這是一個IDs數組,每一個ID用來標識由這個Provider建立的一個App Widget。這樣,若是用戶建立多於一個這個App Widget的實例,那麼它們將被同步更新。不過,對於全部的App Widget實例,只有一個updatePeriodMillis 時間表被管理。好比,若是這個更新時間表被定義爲每隔兩個小時,並且App Widget的第二個實例是在第一個後面一小時添加的,那麼它們將按照第一個所定義的週期來更新而第二個被忽略(它們將都是每2個小時進行更新,而不是每小時)。

注意: 由於這個AppWidgetProvider 是一個廣播接收器BroadcastReceiver,不能保證你的進程在回調函數返回後仍然繼續運行(參見應用程序基礎>廣播接收器的生命週期Application Fundamentals > Broadcast Receiver Lifecycle以獲取更多信息)。若是你的App Widget設置過程能持續幾秒鐘(也許當執行網頁請求時)並且你要求你的進程繼續,考慮在onUpdated()方法裏啓動一個服務Service從這個服務裏,你能夠執行本身的App Widget更新,而沒必要擔憂AppWidgetProvider 因爲一個應用程序無響應錯誤Application Not Responding (ANR)而關閉。參見Wiktionary sample's AppWidgetProvider,這是個App Widget運行一個Service的例子。

一樣參見ExampleAppWidgetProvider.java 例子類。

接收App Widget廣播意圖

 

AppWidgetProvider 只是一個簡便類。若是你想直接接收App Widget 廣播,你能夠實現本身的BroadcastReceiver 或者重寫onReceive(Context, Intent) 回調函數。你須要注意的4個意圖以下:

·         ACTION_APPWIDGET_UPDATE

·         ACTION_APPWIDGET_DELETED

·         ACTION_APPWIDGET_ENABLED

·         ACTION_APPWIDGET_DISABLED

 

建立一個App Widget 配置活動

若是你想讓用戶在添加一個新的App Widget時調整設置,你能夠建立一個App Widget配置活動。這個活動將被App Widget宿主自動啓動並容許用戶在建立時配置可用的設置,好比App Widget顏色,尺寸,更新週期或者其它功能設置。

這個配置活動應該在Android清單文件中聲明爲一個通用活動。不過,它將被經過ACTION_APPWIDGET_CONFIGURE活動而被App Widget宿主啓動,所以這個活動須要接受這個意圖。好比:

<activity android:name=".ExampleAppWidgetConfigure">

    <intent-filter>

        <action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />

    </intent-filter>

</activity>

一樣的,活動必須在AppWidgetProviderInfo XML 文件中聲明,經過android:configure屬性(參見上面的添加AppWidgetProviderInfo元數據Adding the AppWidgetProviderInfo Metadata)。好比,配置活動能夠聲明以下:

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"

    ...

    android:configure="com.example.android.ExampleAppWidgetConfigure"

    ... >

</appwidget-provider>

注意這個活動是用全名聲明的,由於它將從你的程序包外被引用。

這就是全部關於配置活動你一開始須要瞭解的。如今你須要一個真實的活動。這兒就有,不過,當你實現這個活動時記住兩件重要的事情:

•  App Widget 宿主調用配置活動並且配置活動應該老是返回一個結果.這個結果應該包含這個經過啓動該活動的意圖傳遞的App Widget ID(以EXTRA_APPWIDGET_ID保存在乎圖的附加段Intent extras中)

•  當這個 App Widget 被建立時將不會調用onUpdate() 方法(當一個配置活動啓動時,系統將不會發送ACTION_APPWIDGET_UPDATE廣播).配置活動應該在 App Widget 第一次被建立時負責從AppWidgetManager請求一個更新.不過, onUpdate() 將在後續更新中被調用-只忽略第一次.

參見下面章節的代碼片段,該示例說明了如何從配置中返回一個結果並更新這個App Widget.

從配置活動中更新一個App Widget

 

當一個App Widget使用一個配置活動,那麼當配置結束時,就應該由這個活動來更新這個App Widget.你能夠直接AppWidgetManager裏請求一個更新來這麼作.

下面是恰當的更新App Widget 以及關閉配置活動這個過程的一個概要描述:

  1. 首先,從啓動這個活動的意圖中獲取App Widget ID:

    Intent intent = getIntent(); Bundle extras = intent.getExtras(); if (extras != null) {     mAppWidgetId = extras.getInt(             AppWidgetManager.EXTRA_APPWIDGET_ID,              AppWidgetManager.INVALID_APPWIDGET_ID); }
  2. 實施你的App Widget 配置。

  3. 當配置完成後,經過調用getInstance(Context)獲取一個AppWidgetManager實例:

    AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
  4. 以一個RemoteViews佈局調用updateAppWidget(int, RemoteViews)更新App Widget:

    RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.example_appwidget); appWidgetManager.updateAppWidget(mAppWidgetId, views);
  5. 最後,建立返回意圖,設置活動結果,並結束這個活動:

  6. Intent resultValue = new Intent(); resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId); setResult(RESULT_OK, resultValue); finish();

提示: 當你的配置活動第一次打開時,設置活動結果爲RESULT_CANCELED。這樣,若是用戶在結束以前從活動外返回,這個App Widget 宿主會接收到配置取消通知而不會添加這個App Widget。

參見ApiDemos裏面的ExampleAppWidgetConfigure.java 例子。


by iefreer

相關文章
相關標籤/搜索