2010年12月18日 星期六

鬧鐘程式, App Widgets

Android Source Code Internals - Alarm Clock, App Widgets (2)
從 Android v1.5 開始,終於開放 APIs,讓第三方開發者可以寫些 widgets,讓使用者可以放在手機的桌面上。一般手機就有內建幾個小 widgets,其中的 "Analog Clock" widget,就是由 Alarm Clock 這隻鬧鐘程式所提供的。
這次我們就來研究一下,這個 Analog Clock widget 是如何寫出來的。
不過,如果你對如何寫 App Widgets 一點概念都沒有的話,底下有幾個很好的參考資料,一定要先讀過:
要寫個 App Widget,首先你要先用 XML 寫個 AppWidgetProviderInfo,而且這個檔案建議放在 res/xml 中。在鬧鐘程式中,你可以找到 res/xml/analog_appwidget.xml 這個檔案。它的內容如下:
  1. //res/xml/analog_appwidget.xml  
  2. <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"  
  3.   android:minWidth="146dip"  
  4.   android:minHeight="146dip"  
  5.   android:updatePeriodMillis="0"  
  6.   android:initialLayout="@layout/analog_appwidget" >  
  7. </appwidget-provider>  
由 minWidth 及 minHeight 這兩個屬性來看,就可以了解,這個 App Widget 要佔桌面 2x2 cells 大小的空間。
updatePeriodMillis 的值為 0?那這個時鐘是如何自己動的呢?這我在 Android 原始碼徹底研究系列 - 鬧鐘程式, AnalogClock (1) 一文中,就已經解釋過 Analog Clock 是如何自我更新的。還不清楚的,先讀一下這篇。
initialLayout 這個屬性,從名字看起來,就知道它是用來描述這個 App Widget 的畫面設計。由其值我們可以知道,這個 App Widget 的畫面設計,是在 res/layout/analog_appwidget.xml 中。它的內容如下:
  1. //res/layout/analog_appwidget.xml  
  2. <AnalogClock xmlns:android="http://schemas.android.com/apk/res/android"  
  3.   android:dial="@drawable/appwidget_clock_dial"  
  4.   android:hand_hour="@drawable/appwidget_clock_hour"  
  5.   android:hand_minute="@drawable/appwidget_clock_minute"  
  6.   android:layout_width="fill_parent"  
  7.   android:layout_height="fill_parent" />  
果然不出我們所料,這個 App Widget 的畫面設計,就只是一個簡單的 AnalogClock 。時鐘與時,分針圖檔就是分別透過 dial, hand_hour, hand_minute 這三個屬性來指定。
要注意的是,目前在 App Widget 的畫面設計檔中,你只能使用 FrameLayout, LinearLayout, RelativeLayout, AnalogClock, Button, Chronometer, ImageButton, ImageView, ProgressBar, TextView 等元件,其他元件都不能用。
寫好 AppWidgetProviderInfo XML 檔與 App Widget 畫面設計檔,別忘了,還要在 AndroidManifest.xml 中,宣告你的 App Widget Provider。
  1. //AndroidManifest.xml, #55~#60  
  2. <receiver android:name="AnalogAppWidgetProvider"   
  3.           android:label="@string/analog_gadget">  
  4.   <intent-filter>  
  5.     <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />  
  6.   </intent-filter>  
  7.   <meta-data android:name="android.appwidget.provider"   
  8.              android:resource="@xml/analog_appwidget" />  
  9. </receiver>  
在這裡,他指明了這個 App Widget Provider 是要由 AnalogAppWidgetProvider 這個類別來處理。這個類別的原始碼就是 AnalogAppWidgetProvider.java
  1. //#49~#65  
  2. public class AnalogAppWidgetProvider extends BroadcastReceiver {  
  3.   static final String TAG = "AnalogAppWidgetProvider";  
  4.   
  5.   public void onReceive(Context context, Intent intent) {  
  6.     String action = intent.getAction();  
  7.           
  8.     if (AppWidgetManager.ACTION_APPWIDGET_UPDATE.equals(action)) {  
  9.       RemoteViews views = new RemoteViews(context.getPackageName(),  
  10.                                           R.layout.analog_appwidget);  
  11.         
  12.       int[] appWidgetIds = intent.getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS);  
  13.               
  14.       AppWidgetManager gm = AppWidgetManager.getInstance(context);  
  15.       gm.updateAppWidget(appWidgetIds, views);  
  16.     }  
  17.   }  
  18. }  
在這個類別中,主要的工作就是建立 App Widget,並透過 AppWidgetManager 發佈到桌面上。
鬧鐘程式所提供的 "Analog Clock" widget,其實功能很陽春,也沒有用到所有 App Widgets 提供的所有功能。不過,對於想要了解如何寫個 App Widget 的你,應該是有很大的幫助。如果你想要找個較為完整的 App Widget 範例,我建議你看一下 API Demos 這個範例程式。

資料來源:
http://ysl-paradise.blogspot.com/2009/08/android-app-widgets-2.html

沒有留言:

張貼留言