1 Widget简介
Android widget 也称为桌面插件,其是android系统应用开发层面的一部分,但是又有特殊用途,而且会成为整个android系统的亮点。
2 创建一个Widget骨架
先让我们来看一下开发一个可以显示在桌面上的Widget骨架的方法吧。
注意,这个骨架只有简单的显示在桌面(通过“长按桌面->添加桌面小部件”的方法)的功能。
一般来说,一个widget程序应该具有以下几个部分:
1 继承AppWidgetProvider的一个实现
2 widget外观布局的定义文件
3 widget参数配置文件
4 新增widget时的配置Activity的实现(可选)
2.1 继承AppWidgetProvider的一个实现
AppWidgetProvider类继承自BroadcastRecevier,在AppWidget应用update,enable,disable和delete时接收通知。
主要代码如下:
public class WidgetTest extends AppWidgetProvider {
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
// TODO Auto-generated method stub
// 功能代码
}
……
}
我们的WidgetTest类从AppWidgetProvider类继承了这些方法:
1onDeleted(Context context, int[] appWidgetIds)
2onDisabled(Context context)
3onEnabled(Context context)
4onReceive(Context context, Intent intent)
5onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds)
通常情况下,我们重写onUpdate和onReceive方法即可完成所需的功能。OnUpdate方法在Widget应用在桌面上生成时调用,并更新应用UI。OnReceive方法在接收到广播时调用。
2.2 widget外观布局的定义文件
这个文件负责定义widget的外观,它的作用和普通的activity应用的XML布局文件的功能类似。这个文件的书写方法可以直接参考普通的布局文件的写法。
在res\layout文件夹下建立一个xml文件。或者直接修改创建工程后的main.xml文件。
如果我们的widget只是一个图标的话,那么在布局文件中只需要一个imageView控件,就可以完成了。当然,这种情况下,效果和将手机中的应用图标直接拖到桌面上差不多了。
下面这段代码就是演示这种只有一个图标的效果的:
<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/my_widget_img"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_launcher"
android:clickable="true"/>
或者可以用几个textView来模拟一个登录界面,用listView来显示更多的数据,需要用到的组件取决于widget的功能。
2.3 widget参数配置文件
这个参数配置文件说明了我们使用的布局文件,以及一些widget的信息。
我们在res文件夹下创建一个新的文件夹xml,再新建一个xml文件widgettest.xml
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="72dp" android:minHeight="72dp"
android:updatePeriodMillis="86400000" android:initialLayout="@layout/main"
android:configure="com.nahe.wigetTest.WidgetTestConf">
</appwidget-provider>
其中,minWidth和minHeight用来指定widget的大小,也就是我们的widget在桌面上占用几个格子。72dp的长宽是对于“一个格子”的android平台推荐的一个最佳实践值。
UpdatePeriodMillis用来指定widget刷新周期,从省电的角度,一般这个值都比较大。
InitialLayout用来关联2.2中提到的外观布局文件。
Configure是一个可选值,用来关联配置用的Activity。这个activity会在widget需要启动的时候先启动起来。
2.4 在AndroidManifest中注册
为了声明我们的widget,需要在AndroidManifest.xml文件中声明一个receiver,并且用metadata关联到我们自己的appWidgetProvider实现上。
如果只是桌面图标,则不需要activity标签了。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.nahe.wigetTest"
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=".WidgetTest">
<intent-filter>
<action
android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="@xml/widgettest" />
</receiver>
</application>
</manifest>
在reciver中,name属性指向继承了AppWidgetProvider的类WidgetTest。在receiver中,过滤android.appwidget.action.APPEIDGET_UPDATE.
在metadata标签中关联了2.3中提到的配置文件。
到此为止,我们完成了一个简单的widget骨架的开发。
添加widget具体功能
在上一节中,我们提到了一个配置Activity,当用户在桌面上添加小部件的时候,widget首先会运行这个Activity,让用户进行一些选择,比如选择小部件图标等。我们可以在这个Activity中设置widget的点击事件。这一点对于复杂的widget布局也是同样适用的~
为了实现widget的点击响应,我们需要新建一个Activity。这个Activity在widget被点击之后弹出。它和普通的Activity是一样的,需要一个java文件和它的一个xml配置文件。为了方便下文描述,暂时叫这个Activity为widgetEditActivity.java。具体实现不在赘述。
为了给widget添加点击响应,我们需要修改上面提到的配置Activity的代码。为widget添加一个pendingIntent,这样当widget被点击时,就可以触发指定的Intent,从而打开widgetEditActivity了。
Intent intent = new Intent(widgetTestConf.this, widgetEditActivity.class);
intent.setAction(mPerfName + mAppWidgetId);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,mAppWidgetId);
PendingIntent pendingIntent = PendingIntent.getActivity(widgetTestConf.this, 0, intent, 0);
views.setOnClickPendingIntent(R.id.my_widget_img, pendingIntent);
最后,在AndroidManifest.xml中,添加widgetEditActivity的声明。
4 相关类介绍
AppWidgetManager类:
l bindAppWidgetId(int appWidgetId, ComponentName provider)
通过给定的ComponentName 绑定appWidgetId
l getAppWidgetIds(ComponentName provider)
通过给定的ComponentName 获取AppWidgetId
l getAppWidgetInfo(int appWidgetId)
通过AppWidgetId 获取 AppWidget 信息
l getInstalledProviders()
返回一个List<AppWidgetProviderInfo>的信息
l getInstance(Context context)
获取 AppWidgetManger 实例使用的上下文对象
l updateAppWidget(int[] appWidgetIds, RemoteViews views)
通过appWidgetId 对传进来的 RemoteView 进行修改,并重新刷新AppWidget 组件
l updateAppWidget(ComponentName provider, RemoteViews views)
通过 ComponentName 对传进来的 RemoeteView 进行修改,并重新刷新AppWidget 组件
l updateAppWidget(int appWidgetId, RemoteViews views)
通过appWidgetId 对传进来的 RemoteView 进行修改,并重新刷新AppWidget 组件
5 参考文献
[1] Android Widget开发详解 http://developer.51cto.com/art/201007/213558.htm
[2] Android widgets应用学习笔记 http://mobile.51cto.com/widget-290434.htm