一個簡單的AppWidget

    其實Appwidget是一個小型的Views,可以嵌入到其他應用程序並且定期更新。這些View被稱為Widgets組件,您可以通過AppwidgetProvider去發佈Widgets,能夠容納其他Appwidget的稱為Appwidget host。

 

1.1 在AndroidManifest.xml中註冊AppWidget

[html] view plaincopyprint?
<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屬性,它指定Appwidget所使用的AppwidgetProvider.

<intent-filter>至少需要包含 android:name="android.appwidget.action.APPWIDGET_UPDATE",這個屬性指定AppwidgetProvider接收APPWIDGET_UPDATE廣播,這是唯一一個需要明確聲明的廣播。當需要時,AppWidgetManaget自動給所有Appwidget發生廣播.

<meta-data>指定瞭AppwidgetProviderInfo資源,需要一下屬性:android:name  指定metadata的名字。使用android.appwidget.provider將其作為AppwProviderInfo的描述性數據

Android:resource 指定AppwidgetProviderInfo資源的位置

 

1.2 增加AppwidgetProviderInfo Metadata
一個Appwidget的基本屬性是通過AppwidgetproviderInfo去定義的,例如它的最小尺寸的佈局,它的初始layout,多久更新Appwidget,還有(可選)在創建時期配置一個Activity。在xml資源中定義一個AppwidgetproviderInfo是通過<appwidget-provider>標簽,並保存在工程的res/xml/文件夾下,例如:

[html] view plaincopyprint?
(AppWidget特有的配置文件) 
 
<?xml version="1.0" encoding="utf-8"?> 
 
<appwidget-provider  
 
xmlns:android="https://schemas.android.com/apk/res/android" 
 
    android:minWidth="220dp" 
 
    android:minHeight="220dp" 
 
    android:updatePeriodMillis="86400000" 
 
    android:initialLayout="@layout/firstappwidget" 
 
Android:configure="com.example.android.ExampleAppWidgetConfigure"/>  

updatePeriodMillis屬性定義瞭Appwidget應該多久向Appwidgetprovider請求更新。實際更新的時間未必能保證及時更新,並且建議盡量不要頻繁更新。
Configure屬性是當用戶添加一個AppWidget前啟動一個Activity,這個Activity的作用就是配置Appwidget的屬性。

 

1.3 為Appwidget定義layout
          隻要你屬性用xml怎麼去定義layout的話,為appwidget定義一個layout還是很簡單的。但是由於Appwidget的佈局是基於RemoteVIew,所以隻能使用RemoteViews(後面篇章將會對RemoteViews做詳細分析)所支持的 layout(FrameLayout,LinearLayout,RelativeLayout)或者view(AnalogClock, Button , Chronometer ,ImageButton, ImageView, ProgressBar, TextView註意:繼承這些類的子類同樣不支持)。

 

1.4 使用Appwidgetprovider
Appwidgetprovider是BroadcastReceiver的子類,這個類處理Appwidget的廣播。

Appwidgetprovider隻接受於Appwidget有關系的廣播,比如Appwidget在update,deleted,enabled,disable。當這些廣播發生的時候,AppWidgetProvider會調用一下回調方法:

[java] view plaincopyprint?
onUpdate(Context, AppWidgetManager, int[]) 

間隔調用此方法去更新Appwidget,間隔時間的設置時在AppwidgetproviderInfo下的updatePeriodMillis屬性,同樣當用戶添加Appwidget的時候也被調用。如果你已經聲明瞭一個configuration Activity,用戶添加Appwidget的時候就不會調用onUpdate,但是隨後的更新中依然會被調用。

onDeleted(Context, int[])

當Appwidget從Appwidget host中刪除的時候調用

onEnabled(Context);

當Appwidget第一次創建的時候調用。比如,當用戶增加兩個同樣的Appwidget的時候,這個方法隻在第一次去調用。如果你需要打開一個新的數據庫或者其他的設置,而這在所有的Appwidget隻需要設置一次的情況下,這個是最後的地方去實現它們。

onDisabled(Context)

當Appwidget的最後一個實例從Appwidget host中刪除的時候調用。這裡可以做一些在onEnabled(Context)中相反的操作,比如刪除臨時數據庫。

onReceive(Context, Intent)

每一個廣播的產生都會調用此方法,而且是在上面方法之前被調用。通常不需要實現此方法(這個方法在後面會作詳細分析)。

在AppwidgetProvider中最重要的callback就是onUpdated(),如果你的Appwidget接受用戶交互事件,就需要在這個callback裡面進行處理。

如果你需要一個帶有Button的Appwidget,點擊Button去啟動一個Activity,下面就是AppwidgetProvider的實現方法:

 

[java]
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 tothe 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 
    WidgetappWidgetManager.updateAppWidget(appWidgetId, views); 


1.5 創建Appwidget Configuration Activity

這個Activity將通過Appwidget自動啟動,用戶可以給Appwidget設置有用的參數,比如Appwidget的顏色,大小,更新時間或者其他的屬性。

在AndroidManifes.xml中定義這個Activity和一般定義Activity基本沒有區別,Appwidget host啟動這個Activity需要一個Action,所以:

 

[java]
<activity android:name=".ExampleAppWidgetConfigure"> 
<intent-filter> 
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE"/> 
</intent-filter> 
</activity>  

同樣這個Activity必須在AppwidgetProviderInfo XML文件中定義android:configure.

值得註意的是Appwidget host調用configuration Activity,configuration Activity必須要返回一個結果(必須包含Appwidget ID)saved in the Intent extras as EXTRA_APPWIDGET_ID

 

1.6 通過configuration Activity去更新Appwidget
獲取Appwidget ID

[java]www.aiwalls.com
Intent  intent = getIntent(); 
Bundle extras = intent.getExtras(); 
If(extras != null){ 
    mAppWidgetId = extras.getInt( 
    AppWidgetManager.EXTRA_APPWIDGET_ID,AppwidgetManaget.INVALID_APPWIDGET_ID); 

設置Appwidget參數

設置完成,通過getInstance(Context)獲取AppwidgetManager實例

[java]
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context); 
通過調用updateAppWidget(int,RemotrViews)去更新Appwidget

[java]
RemoteViews views = new RemoteViews(context.getPackageName(), 
R.layout.example_appwidget); 
appWidgetManager.updateAppWidget(mAppWidgetId, views);  

創建一個返回的Intent,結束Activity

[java]
Intent resultValue = new Intent(); 
resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,mAppWidgetId); 
setResult(RESULT_OK, resultValue);  

android:initialLayout="@layout/firstappwidget"指定瞭下面的佈局文件firstappwidget.xml
[java]
<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android" 
    android:orientation="vertical"  
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent"> 
<TextView android:id="@+id/tvMsg" android:layout_width="fill_parent" 
    android:layout_height="wrap_content" android:textSize="20dp" 
    android:textColor="#F00"/> 
</LinearLayout>  
作者:fangchongbory

發佈留言