Android Widget簡介
應用程序窗口小部件(Widget)是微型的應用程序視圖,它能夠被嵌入到其它應用程序中(好比桌面)並接收週期性的更新。你能夠經過一個App Widget Provider來發佈一個Widget。能夠容納其它App Widget的應用程序組件被稱爲App Widget宿主程序.
爲了建立一個App Widget,你須要使用下面這些:
1.AppWidgetProviderInfo 對象(定義在XML文件裏面)
描述一個App Widget元數據,好比App Widget的佈局,更新頻率,以及AppWidgetProvider 類。這個應該在XML裏定義。
2.AppWidgetProvider 類的實現(主要是接收廣播並進行相應操做)
定義基本方法以容許你經過編程來和App Widget通訊,這基於廣播事件。經過它,當App Widget被更新、可用、禁用和刪除的時候,都將接收到廣播通知。
3.視圖佈局
在XML中定義App Widget初始佈局。
另外,你能夠實現App Widget配置Activity 。這是一個可選的Activity,當用戶添加App Widget時加載它並容許用戶修改App Widget的設置。(當用戶添加到桌面時會自動調用該Activity)
Android Widget具體使用
1.首先,在應用程序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>
說明:html
<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.appwidget.provider 來 肯定AppWidgetProviderInfo描述的數據。
- android:resource–指定AppWidgetProviderInfo 資源路徑。
2.添加AppWidgetProviderInfo元數據
AppWidgetProviderInfo定義一個App Widget的基本特性,好比最小布局尺寸,初始佈局資源,刷新頻率,以及建立時加載的一個配置Activity(可選的)。使用單獨的一個<appwidget-provider>元素在XML資源裏定義AppWidgetProviderInfo 對象並保存到項目的res/xml/目錄下
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="294dp"
android:minHeight="72dp"
android:updatePeriodMillis="86400000"
android:initialLayout="@layout/example_appwidget"
android:configure="com.example.android.ExampleAppWidgetConfigure" >
</appwidget-provider>
下面是<appwidget-provider>屬性的總結: java
a)minWidth 和minHeight 屬性的值指定了App Widget佈局須要的最小區域。android
缺省的App Widgets所在窗口的桌面位置基於有肯定高度和寬度的單元網格中。若是App Widget的最小長度或寬度和這些網格單元的尺寸不匹配,那麼這個App Widget將上舍入(上舍入即取比該值大的最接近的整數——譯者注)到最接近的單元尺寸。數據庫
通常說來桌面佈局方向能夠變化(由此單元的尺寸也會變化),你應該假設最壞狀況即單元尺寸高和寬是74像素。不過,你必須從最終的尺寸中減去2以把像素計算過程當中產生的任何的整數舍入偏差考慮在內。要找到像素密度無關的最小寬度和高度,使用這個公式:(number of cells * 74) - 2.依據這個公式,你應該使用72dp做爲高度,294dp做爲寬度。編程
b)updatePerdiodMillis 屬性定義了App Widget框架調用onUpdate()方法來從AppWidgetProvider請求一次更新的頻度。實際更新時間並不那麼精確,並且咱們建議更新頻率越低越好——最好每小時不超過一次以節省電源。你也許還會容許用戶在配置中調整這個頻率——一些人可能想每15分鐘一次股票報價,或者一天只要四次。app
注意:當到個更新的時間時,若是設備處於休眠狀態,則設備將會被喚醒來執行更新操做。若是更新頻率每小時不超過一次,這可能對電池的壽命不會產生值得注意的問題。可是,若是更新的很頻繁,或者當設備處於休眠狀態時不更新,那麼你最好使用一個alarm來代替執行更新操做,這樣不會喚醒設備。這種方式能夠經過使用AlarmManager類實現。設置alarm的類型爲 ELAPSED_REALTIME或者RTC,這兩種類型只有在設備處於喚醒狀態時纔會傳遞alarm,同時設置updatePeriodMillis 爲0.框架
c)initialLayout屬性指向定義App Widget佈局的資源。ide
d)configure屬性定義了當用戶添加App Widget時啓動的Activity,配置App Widget特性。這是可選的函數
3.建立App Widget佈局oop
你必須在XML中爲你的App Widget定義一個初始佈局並保存到項目的res/layout/ 目錄下。你可使用以下所列的View對象來設計你的App Widget,可是,你必須注意App Widget佈局是基於RemoteViews, 而RemoteViews並不支持全部類型的佈局或視圖小部件。
一個RemoteViews對象(對應的,一個App Widget)能夠支持下面這個佈局類(可是不支持這些類的派生):
-
- FrameLayout
- LinearLayout
- RelativeLayout
以及下面的控件類:
-
- AnalogClock
- Button
- Chronometer
- ImageButton
- ImageView
- ProgressBar
- TextView
4.使用AppWidgetProvider類
AppWidgetProvider類擴展自BroadcastReceiver ,做爲處理App Widget廣播一個簡便類,AppWidgetProvider只接收和這個App Widget相關的事件廣播,好比這個App Widget被更新、刪除、啓用以及禁用。當這些廣播事件發生時,AppWidgetProvider 將接收到下面的方法調用:
onUpdate(Context, AppWidgetManager, int[]) //最經常使用的由於它是在每一個App Widget添加進宿主時被調用的(除非你使用一個配置活動)
這個方法調用來間隔性的更新App Widget,間隔時間用AppWidgetProviderInfo 裏的updatePeriodMillis屬性定義。這個方法也會在用戶添加App Widget時被調用,所以它應該執行必要的設置,好比爲控件定義事件處理器並啓動一個臨時的服務Service,若是須要的話。可是,若是你已經聲明瞭一個配置Activity,這個方法在用戶添加App Widget時將不會被調用,而只在後續更新時被調用。配置Activity有責任在配置完成時負責執行第一次更新。
onDeleted(Context, int[])
當App Widget從宿主App Widget 中刪除時被調用。
onEnabled(Context)
當一個App Widget實例第一次建立時被調用。好比,若是用戶添加兩個你的App Widget實例,只在第一次被調用。若是你須要打開一個新的數據庫或者執行其餘對於全部的App Widget實例只須要發生一次的設置,那麼這裏是完成這個工做的好地方。
onDisabled(Context)
當你的App Widget的最後一個實例被從宿主中刪除時被調用。你應該在onEnabled(Context)中作一些清理工做,好比刪除一個臨時的數據庫。
onReceive(Context, Intent)
這個接收到每一個廣播時都會被調用,並且在上面的回調函數以前。你一般不須要實現這個方法,由於缺省的AppWidgetProvider 實現過濾全部App Widget 廣播並恰當的調用上述方法。
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 是一個廣播接收器BroadcastReceiver,不能保證你的進程在回調函數返回後仍然繼續運行。若是你的App Widget設置過程能持續幾秒鐘(好比當執行網頁請求時)並且你要求你的進程繼續,考慮在onUpdated()方法裏啓動一個服務Service。從這個服務裏,你能夠執行本身的App Widget更新,而沒必要擔憂AppWidget Provider 因爲一個應用程序無響應錯誤Application Not Responding (ANR)而關閉。
AppWidgetProvider 只是一個簡便類。若是你想直接接收App Widget廣播,你能夠實現本身的BroadcastReceiver 或者重寫 onReceive(Context, Intent) 回調函數。你須要注意以下4個Intents
- ACTION_APPWIDGET_UPDATE
- ACTION_APPWIDGET_DELETED
- ACTION_APPWIDGET_ENABLED
- ACTION_APPWIDGET_DISABLED
5.建立一個App Widget 配置Activity()
若是你想讓用戶在添加一個新的App Widget時調整設置,你能夠建立一個App Widget配置Activity 。這個Activity 將被App Widget宿主自動啓動並容許用戶在建立時配置可用的設置,好比App Widget顏色,尺寸,更新週期或者其它功能設置。
這個配置Activity應該在Android清單文件中聲明爲一個通用Activity。不過,它將被經過ACTION_APPWIDGET_CONFIGUREaction而被App Widget宿主啓動,所以這個Activity須要接受這個Intent 。好比:
固然,Activity必須在AppWidgetProviderInfo XML 文件中聲明,經過android:configure屬性。好比,配置Activity能夠聲明以下:
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
...
android:configure="com.example.android.ExampleAppWidgetConfigure"
... >
</appwidget-provider>
注意這個Activity是用全包名聲明的,由於它將從你的程序包外被引用。
這就是全部關於配置活動你一開始須要瞭解的。如今你須要一個真實的Activity。這兒就有,不過,當你實現這個Activity時記住兩件重要的事情:
-
- App Widget 宿主調用配置Activity並且配置Activity應該老是返回一個結果.這個結果應該包含這個經過啓動該活動的意圖傳遞App Widget ID(以EXTRA_APPWIDGET_ID保存在Intent的附加段Intent extras中)
- 當這個 App Widget 被建立時將不會調用onUpdate() 方法(當一個配置活動啓動時,系統將不會發送ACTION_APPWIDGET_UPDATE廣播).配置活動應該在 App Widget 第一次被建立時負責從AppWidgetManager請求一個更新.不過, onUpdate() 將在後續更新中被調用-只忽略第一次.
從配置Activity中更新一個App Widget
當一個App Widget使用一個配置Activity,那麼當配置結束時,就應該由這個Activity來更新這個App Widget.你能夠直接經過AppWidgetManager請求一次更新操做.下面是恰當的更新App Widget 以及關閉配置Activity這個過程的一個概要描述:
1.首先,從啓動這個Activity的Intent中獲取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:
5.最後,建立返回Intent ,設置到Activity結果,並結束這個Activity: