先来看下项目结构,以便读者有个整体的把握
下面详细介绍各个文件的作用:
首先在res文件夹下新建一个名为xml的文件夹,在此文件夹中新建一个xml文件,这里命名为example_appwidget_info.xml(可随意命名),该文件内容如下:
此文件描述appWidget的参数信息,从上到下分别为高度、宽度、刷新时间间隔、布局文件,此处布局文件引用了layout文件夹下的example_appwidget.xml,此文件用来描述appWidget中内容的布局,下面来看看这个文件的内容
此文件的布局同activity的布局,不做过多解释,这里只简单定义了一个TextView,内容为“firstWidgetText”定义完了appWidget,接下来新建一个类继承AppWidgetProvider,用来处理appWidget中控件产生的事件,这里将这个类命名为ExampleAppWidgetProvider
这里复写了4个父类方法,分别为onUpdate(到达指定的更新时间或者当用户向桌面添加AppWidget时被调用)、onEnabled(AppWidget的实例第一次被创建时调用)、onDisabled(最后一个appWidget被删除时调用)、onDeleted(删除一个AppWidget时调用)。4个方法都只简单输出各自方法名用来判断调用情况
其实这个类是个receiver,何以见得?从AndroidManifest.xml可以找到答案,下面就来看看这个文件
看红框部分,注册了name为ExampleAppWidgetProvider的receiver,而ExampleAppWidgetProvider就是上文中提到类的类名, intent-filter中的action是系统自带的用于更新所有appwidget的广播动作, meta-data标签是一个描述我们创建appwidget的元数据,android:name="android.appwidget.provider"是固定的,android:resource="@xml/example_appwidget_info"用来指定appWidget配置文件的位置,即上文中介绍的example_appwidget_info.xml,用来初始化appWidget
到此,程序已可以在桌面上添加小窗口,读者可尝试运行添加AppWidget,看看receiver的方法的调用的情况,截图如下
前面的内容介绍了如何创建一个appWidget,但目前appWidget没有任何的交互功能,下面介绍appWidget如何与程序交互。首先要考虑一个问题,appWidget的进程和应用的进程是两个不同的进程,能通过引用控件来获得实例吗,当然是不行的。这时候需要一个对象叫做RemoteViews,能帮助我们获得不在同一进程中的对象,下面的代码演示了RemoteView的使用
实例化RemoteView时的参数还是容易理解的,一个是layout resource的包名,另一个是layout resource,难理解的是监听语句中的pendingIntent,笔者也找了一些资料,其中一种说法是, “PendingIntent可以看成是一个特殊的Intent,如果我们把Intent看成一封信,那么PendingIntent就是一封被信封包裹起来的信。这封信在remoteViews.setOnClickPendingIntent()中被“邮寄”到了appwidget, 当appwidget中的按钮单击时他知道将这封信打开,并执行里面的内容。这样就避免了直接从appwidget中执行本地代码”。 笔者的理解正好相反,不是将 PendingIntent “邮寄”到了appwidget ,而是在应用的进程里取到appWidget中所有控件的实例remoteViews, AppWidget只是把一个进程的控件嵌入到别外一个进程的窗口里的一种方法。View在另 外一个进程里显示,但事件的处理方法还是在原来的进程里。读者可以自行理解这部分的内容,有什么不同的意见可以留言说明理由,但可以肯定的是 pendingIntent是用来当点击appWidget控件时出发的Intent,下面来看看PendingIntent的定义:介绍了以上的知识点以后,来看看ExampleAppWidgetProvider的onUpdate方法的整体实现,应该不难理解
创建一个Intent对象,从contex跳转到TargetActivity,,TargetActivity为最简单的activity(创建时生成),用getActivity创建一个PendingIntent,然后初始化一个RemoteView对象,调用setOnclickClientPending方法,当点击R.id.widgetButtonId时执行pendingIntent,然后更新appWidget.这里引用的 R.id.widgetButtonId 定义在example.xml中
下面来看一下执行的效果
添加appWidget后:
点击button后跳转到TargetActivity
上文中实现了appWidget的交互,但只是实现了Activity的跳转,下面实现用appWidget接收一个广播
首先修改上文中提到过的onUpdate方法,如图
通过过滤器后,会在AppWidgetProvider类中的onReceive方法接收到广播,因为ExampleAppWidgetProvider类继承AppWidgetProvider,所以在此类中复写onReceive方法
最后来看下执行的效果
添加appWidget后:
点击button后:
这里因为笔者引用的图片很大,所以把下面的button挤掉了,读者可忽略此问题。
---------------------------------------------------------------------------------
转自:http://www.taobaotest.com/blogs/2296