App Widget也是一种UI组件,它可以让一小块程序(program piece)嵌入到桌面上。与普通的Widget(TextView、WebView等)相比,有以下几个不同:
应用上,由于App Widget自动更新的特性,所以它比较适合用来设计一些天气,新闻,日历等功能。
App Widget的设计流程:
及设计一个App Widget至少需要以下4个文件:
下面是一个具体实现App Widget的例子:
新建一个Android工程HelloAppWidget,在/res目录新建一个文件夹xml,在/res/xml目录下新建一个appwidget_provider.xml文件:
<?xml version="1.0" encoding="utf-8"?> <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" android:minWidth="85dp" android:minHeight="30dp" android:updatePeriodMillis="1000" android:initialLayout="@layout/main" > </appwidget-provider>说明如下:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/appwidget_text" android:textColor="#ff0000" /> </LinearLayout>我们的App Widget使用LinearLayout來安排布局,而UI为一个TextView物件。在这里,将此TextView的id定义为”appwidget_text”。
在Android工程中添加一个新类HelloAppWidgetProvider extends AppWidgetProvider:
package com.android; import java.util.Date; import android.appwidget.AppWidgetManager; import android.appwidget.AppWidgetProvider; import android.content.Context; import android.widget.RemoteViews; public class HelloAppWidgetProvider extends AppWidgetProvider { public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { final int N = appWidgetIds.length; for (int i=0; i<N; i++) { int appWidgetId = appWidgetIds[i]; updateAppWidget(context, appWidgetManager, appWidgetId); } } public void onDeleted(Context context, int[] appWidgetIds) { } static void updateAppWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId) { CharSequence text; java.text.DateFormat df = new java.text.SimpleDateFormat("hh:mm:ss"); text = "http://blog.csdn.net/imyang2007" + " Time:" + df.format(new Date()); RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.main); views.setTextViewText(R.id.appwidget_text, text); appWidgetManager.updateAppWidget(appWidgetId, views); } }
在AndroidManifest.xml里我们要让HelloAppWidgetProider类可以接收ACTION_APPWIDGET_UPDATE广播事件;ACTION_APPWIDGET_UPDATE是最主要的App Widget事件,当AppWidgetProvider被要求为App Widget提供”RemoteView”时,就会收到这个事件。
RemoteViews 就是表示UI的类。res/layout/main.xml描述了应用程序的UI,UI里当然包含许多组件(Widget),Android应用程序的UI就是一个View tree,view tree就是View Hierarchy。总结来说,RemotViews是一个用来表示View Hierarchy的类。通过RemoteViews可以找到UI里的每一个组件。
onUpdate()负责更新已经安装在桌面上的App Widget內容,因此我们实现一个updateAppWidget()來进行真正更新的工作。onUpdate()的第二个参数为AppWidgetManager,这是一个管理AppWidgetProvider的类,我们必須通过框架callback本方法时回传给我们的AppWidgetProvider,来更新桌面上的App Widget。onUpdate()第三个参数appWidgetIds阵列,存放需要更新的App Widget ID;框架会将需要更新的App Widget的ID回传给onUpdate(),程序必須负责更新每一个需要更新的App Widget。
updateAppWidget()说明:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="10" /> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" > <receiver android:name=".HelloAppWidgetProvider" > <meta-data android:name="android.appwidget.provider" android:resource="@xml/appwidget_provider" /> <intent-filter> <action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> </intent-filter> </receiver> <activity android:name=".HelloAppWidgetActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
最后,发现一个问题,程序并没有实现我们的预想的每秒更新一次App Widget,而是在30~60分钟更新一次,这是1.6之后的android版本为了使设备不那么耗电,把App Widget的更新时间增加到了30分钟以上。