Android中選取並綁定AppWidget

Android添加一個窗口小部件的過程,實際是AppWidgetHost選取AppWidgetProvider並與之綁定的過程。一般地,Launcher扮演AppWidgetHost角色,AppWidgetProvider可以從所有已安裝的AppWidgetProvider列表中選取。本文以描述選取並綁定AppWidgetProvider的這一過程。

 

一、Launcher發起選取申請

 

在桌面上選取窗口小部件的過程,實際是Launcher,發起選取AppWIdget申請,隻需要用startActivityForResult()並用AppWidgetManager.ACTION_APPWIDGET_PICK為Intent的Action啟動另外的Activity,等待選取的結果。

 Launcher Pick AppWidget ClassHierarchy

圖一、LauncherPick AppWidget類圖

 

Launcher是一個Activity,具有Activity的啟動另外的Activity並等待結果的能力和相應的方法。Launcher中還定義瞭AppWIdgetHost的子類LauncherAppWidgetHost。

 

Launcher發起PickAppWIdget的時序如下圖:

 Launcher Pick AppWidget Sequence Diagram

圖二、LauncherPick AppWidget的順序圖

 

先用AppWidgetHost申請一個AppWidget的ID;
新建一個AppWidgetManager.ACTION_APPWIDGET_PICK的Intent,並把上面申請的appWidgetId作為AppWidgetManager.EXTRA_APPWIDGET_ID的參數,啟動另外的Activity完成AppWidget的選取工作,並等待結果再來處理。

 

發出啟動響應AppWidgetManager.ACTION_APPWIDGET_PICK的Activity之後,Android系統會從已經安裝的apk中選擇Intent-filter中含有AppWidgetManager.ACTION_APPWIDGET_PICK的Activity,並啟動之。

Settings裡的AppWidgetPickActivity是這樣的一個Activity,下面看它如何處理。

 

二、AppWidgetPickActivity靜態結構

 

AppWidgetPickActivity類圖如下:

 Settings AppWidgetPickActivity class Diagram

圖三、AppWidgetPickActivity類圖

 

 AppWidgetPickActivity類繼承關系:AppWidgetPickActivity –>ActivityPicker -> AlertActivity。ActivityPicker中有PickerAdapter,用來PickItem,並在PickerAdapter.Item中填充顯示給用戶所需的數據。
 AppWidgetPickActivity通過AppWidgetManager.getInstalledProviders()獲取已經安裝的所有的AppWidgetProvider,這些AppWidgetProvider的信息以AppWidgetProviderInfo的形式存儲。
 AppWidgetPickActivity 的父類ActivityPicker實現瞭DialogInterface.OnClickListener和DialogInterface.OnCancelListener,可響應用戶的選擇。用戶選擇其中的一個AppWidgetProvider之後,把AppWidgetId與其綁定。

 

三、獲取所有已安裝的AppWidgetProvider

 

圖四是獲取所有已安裝AppWidgetProvider的信息,並生成PickerAdapter.Item的過程。

 Settings AppWidgetPickActivity getInstalledProviders Sequence Diagram

圖四、獲取所有已安裝AppWidgetProvider列表的順序圖

 

AppWidgetPickActivity被創建並啟動的時候,通過AppWidgetManager.EXTRA_APPWIDGET_ID傳入瞭AppWidgetId參數,這裡解析出來並保存;[Seq#1~ #3]
AppWidgetPickActivity的父類ActivityPicker會通過模板模式(TemplatePattern)調用getItems()獲得列表項。AppWidgetPickActivity實現getItems():[Seq#4~ #9]
  通過AppWidgetManager.getInstalledProviders()獲取所有已經安裝的AppWidgetProvider,這些AppWidgetProvider的信息以AppWidgetProviderInfo的形式返回;[Seq#5~ #6]
  創建PickerAdapter.Item,並把AppWidgetProviderInfo中的對應項設置到PickerAdapter.Item內,並把所有的這些Item放入items:ArrayList<PickerAdapter.Item>;[Seq#7 ~ #8]
  從getItems()中返回,並帶回返回值items[Seq#9]

getItems()帶回Item並返回之後,ActivityPicker會把這些項以列表形式顯示出來。接下來,如果用戶選擇其中某項之後,就實現瞭選取AppWidgetProvider並與AppWidgetId綁定。

 

四、選取並綁定一個AppWidgetProvider

 

圖五是用戶選擇一個AppWidgetProvider,把AppWidgetId與其綁定的過程。

 Settings AppWidgetPickActivity Pick and bindAppWidget Sequence Diagram

圖五、選取並綁定AppWidgetProvider的順序圖

 

用戶選擇瞭列表中的某個AppWidgetProvider;[Seq#1]
通過列表中的位置which獲得Intent,實際是Provider的packageName和className設置進瞭Intent的Component裡;[Seq#2 ~ #5]
把圖四#3中獲得的AppWidgetId(也就是Launcher這個AppWidgetHost在圖二#1&2中通過AppWidgetHost申請到的ID)與這個AppWidgetProvider綁定;[Seq#6~ #7]
把選擇的結果通過Activity.setResult()設置,並把appWidgetId以Intent參數形式傳回。[Seq#8~ #10]

這樣啟動AppWidgetPickActivity的Activity也就是Launcher,就會在其onActivityResult()中獲得選擇的結果。

 

因為,獲得結果之後,Launcher所做的工作是作為AppWidgetHost的工作,這將在《Android中AppWidget的分析與應用:AppWidgetHost》中再詳細闡述。

 

五、總結

 Launcher發起選取AppWidgetProvider的動作。
 AppWidgetPickActivity獲得所有已安裝AppWidgetProvider的列表,並呈現給用戶。用戶選擇之後,把AppWidgetId與AppWidgetProvider綁定。
 Launcher作為AppWidgetHost負責把AppWidgetProvider裡通過RemoteViews傳遞的圖形元素顯示出來;並負責用戶操作事件通知到AppWidgetProvider。

 

可進一步參考文章

Android AppWidget框架

    AppWidget系統框架。

Android中選取並綁定AppWidget

    本文。

Android中AppWidget的分析與應用:AppWidgetProvider

    可以看AppWidgetManager/AppWidgetService收集AppWidgetProvider的哪些信息,放在所以已安裝AppWidgetProvider列表裡的。並可以學習AppWidgetProvider如何創建和設置RemoteViews。

Android中AppWidget的分析與應用:AppWidgetHost

    可以看選取並綁定AppWidgetProvider之後,Launcher作為AppWidgetHost如何創建顯示RemoteViews裡AppWidgetProvider所提供的圖形元素。

Android中RemoteViews的實現

    Android中RemoteViews的內部具體實現。

 

發佈留言