其實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="http://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.2cto.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="http://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