Android中AppWidget的分析与应用:AppWidgetProvider
田海立@CSDN
2012-8-20
本文从开发AppWidgetProvider角度出发,看一个AppWidgetPrvodier在整个AppWidget体系中所扮演的角色。分析了AppWidgetProvider如何被AppWidget系统所识别;AppWidgetProvider何时/如何通过RemoteViews提供并更新数据;如何响应通过RemoteViews提供的PendingIntent的按钮点击操作。
因为一般应用开发者并不关注AppWidget其他部分(比如,AppWidgetHost,或AppWidget内部组件)的开发,所以一般就直接把AppWidgetProvider开发称为“AppWidget开发”。
要实现一个AppWidgetProvider,需要:
- 实现AppWidgetProvider的子类,并至少override onUpdate()方法[非必须,但是如果不这样做,该AppWidgetProvider就没有提供任何内容,也就不是AppWidgetProvider了];在AndroidManifest.xml中,声明上述的AppWidgetProvider的子类是一个Receiver,并且:该Receiver的intent-filter的Action必须包含“android.appwidget.action.APPWIDGET_UPDATE”;该Receiver的meta-data为“android.appwidget.provider”,并用一个xml文件来描述布局属性。在2.2的xml文件中描述布局属性的节点名称必须为“appwidget-provider”。
以上几点皆是AppWidget系统判断是否是AppWidgetProvider的标志。后面本文的3.2中详述是如何被检索并加入到系统中的。
二、AppWidgetProvider类分析
AppWidgetProvider是一个BroadcastReceiver,必须在AndroidManifest.xml中声明该Receiver,并接收“android.appwidget.action.APPWIDGET_UPDATE”。
类AppWidgetProvider的实现是一个模板模式:

图一、AppWidgetProvider
在AppWidgetProvider的onReceiver()实现中已经对接收到的ActionAppWidgetManager.ACTION_APPWIDGET_UPDATE / AppWidgetManager.ACTION_APPWIDGET_DELETED/ AppWidgetManager.ACTION_APPWIDGET_ENABLED以及AppWidgetManager.ACTION_APPWIDGET_DISABLED做了处理,分别执行onUpdate()/ onDeleted() / onEnabled() / onDisabled()。
所以,AppWidgetProvider的实现类,要overrideonReceive(),以及onXXX()[注:至少要实现onUpdate(),在这里AppWidgetProvider通过RemoteViews提供内容给AppWidgetHost,否则,所谓的AppWidgetProvider什么也没提供]。
而在onReceive()的开始处就要执行super.onReceive()让AppWidgetProvider来分发AppWidgetProvider所要处理的上述广播消息。
AppWidgetProvider处理AppWidget中的广播:
onUpdate() 处理AppWidgetManager.ACTION_APPWIDGET_UPDATE广播。该广播在需要AppWidgetProvider提供RemoteViews数据时,由AppWidgetService.sendUpdateIntentLocked()发出。onDeleted() 处理AppWidgetManager.ACTION_APPWIDGET_DELETED广播。该广播在有该AppWidgetProvider的实例被删除时,由AppWidgetService.deleteAppWidgetLocked()发出。onEnabled() 处理AppWidgetManager.ACTION_APPWIDGET_ENABLED广播。该广播在该AppWidgetProvider被实例化时,由AppWidgetService.sendEnableIntentLocked()发出。onDisabled() 处理AppWidgetManager.ACTION_APPWIDGET_DISABLED广播。该广播在该AppWidgetProvider的所有实例中的最后一个实例被删除时,由AppWidgetService.deleteAppWidgetLocked()发出。一般地,AppWidgetProvider必须处理onUpdate();onEnabled()和onDisabled()最好也要处理;onDeleted()可以不处理。
三、AppWidgetProvider的如何被系统识别
3.1 AppWidgetProvider中配置AndroidManifest.xml
Android中“电量控制”这个AppWidget是由Settings中的SettingsAppWidgetProvider实现的,先来看它的AndroidManifest.xml。
下面是Settings中关于SettingsAppWidgetProvider这个AppWidgetProvider的描述信息:
图二、AppWidgetProviderInfo
四、AppWidgetProvider的Enable与Disable
因为AppWidgetProvider只是提供显示内容,具体显示是显示在AppWidgetHost中的。因为Android机制的关系,后台的AppWidgetProvider很容易被系统杀掉。所以AppWidgetProvider在收到AppWidgetManager.ACTION_APPWIDGET_ENABLED和AppWidgetManager.ACTION_APPWIDGET_DISABLED而执行的onEnbaled()和onDisabled()中是恰当的设置实现AppWidgetProvider的包能不能被移除设置的恰当点。
在onEnbaled()中,该AppWidgetProvider正在被使用,不让被杀掉:
图三、AppWidgetProvider提供RemoteViews
在onUpdate()中,创建RemoteViews的实例,传入AppWidgteProvider所在的包名和该AppWidget所要用的Layout;[Seq#5] 如果要响应layoutId中某个viewId被点击操作,要创建本地的PendingIntent,并通过setOnClickPendingIntetn设置到RemoteViews中;[Seq#6~ #9] 为layoutId中要显示的控件加上显示元素,比如某个ImageView的ImageResource。[Seq#10] 用AppWidgetManager.updateAppWidget()更新RemoteViews到系统中,AppWidget系统会更新与之绑定的AppWidgetHost。[Seq#11]
RemoteViews设置与显示详细实现可参考《Android中RemoteViews的实现》;AppWidgetHost如何更新RemoteView可参看《Android中AppWidget的分析与应用:AppWidgetHost》。
六、通过PendingIntent设置按钮响应
上面讲到,可以通过给RemoteViews设置PendingIntent获知感兴趣的View被点击时的响应:
if(intent.hasCategory(Intent.CATEGORY_ALTERNATIVE)) { Uri data = intent.getData(); int buttonId = Integer.parseInt(data.getSchemeSpecificPart()); if (buttonId == BUTTON_WIFI) { // 切换Wifi状态 } else if (buttonId == BUTTON_BRIGHTNESS) { // 切换亮度 } else if (buttonId == BUTTON_SYNC) { // 切换数据同步设置 } else if (buttonId == BUTTON_GPS) { // 切换GPS打开开关 } else if (buttonId == BUTTON_BLUETOOTH) { // 切换蓝牙打开状态 } }总结
本文讲述了:
实现一个AppWidgetProvider所需要的配置和实现; AppWidgetProvider如何被AppWidget识别和加入到已安装列表; AppWidgetProvider如何生成RemoteViews对象,并更新到AppWidgetHost; AppWidgetProvider响应按钮操作。可进一步参考的文章
Android AppWidget框架
AppWidget系统框架。
Android中选取并绑定AppWidget
看如何调用本文描述的已经获取的AppWidgetProvider列表的。
Android中AppWidget的分析与应用:AppWidgetProvider
本文。
Android中AppWidget的分析与应用:AppWidgetHost
可以看选取并绑定AppWidgetProvider之后,Launcher作为AppWidgetHost如何创建显示RemoteViews里AppWidgetProvider所提供的图形元素。
Android中RemoteViews的实现
RemoteViews的内部如何实现设置进去的OnClickPendingIntent和ViewImageResource的。
- 1楼thl789昨天 21:19
- 看AppWidgetProvider所有实现类中,都没有在AndroidManifest.xml声明或者显式用registerReceiver()注册接收那些除了AppWidgetManager.ACTION_APPWIDGET_UPDATE之外的其他广播(AppWidgetManager.ACTION_APPWIDGET_DELETED/ AppWidgetManager.ACTION_APPWIDGET_ENABLED以及AppWidgetManager.ACTION_APPWIDGET_DISABLED),那为什么AppWidgetProvider中还能收到这些广播呢?原来这些广播是定向的发送:http://blog.csdn.net/thl789/article/details/7888108