学习Android闹钟源代码(二)-桌面widget类分析

本文深入剖析了Android JellyBean版本中时钟Widget的工作原理。从源代码层面详细介绍了Widget组件的实现过程,包括如何响应更新广播、使用RemoteViews设置点击事件以及PendingIntent的创建等关键技术点。

一,项目初看

  (事先要说明的一点就是,我使用的是android4.1的源代码哦,虚拟机也是Jelly Bean的哦。

 (1)项目主要由com.android.deskclock及com.android.alarmclock组成。总共

  26个源文件

其中最简单的一个要数Log.java类了,相信只要有基本的Java基础的人都能够看懂。

 从AndroidManifest.xml文件中可以看出,应用的入口是DeskClock.java文件的DeskClock类.

二,进入应用,Jelly Bean的虚拟机的话,应用的主界面,就有一个时钟。

  显然这个时钟是一个Widget。我们就先来看看这个吧。widget在清单文件中上的声明吧:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
< receiver
            android:name = "com.android.alarmclock.AnalogAppWidgetProvider"
            android:icon = "@mipmap/ic_widget_analog_clock"
            android:label = "@string/analog_gadget" >
            < intent-filter >
                < action android:name = "android.appwidget.action.APPWIDGET_UPDATE" />
            </ intent-filter >
 
            < meta-data
                android:name = "android.appwidget.oldName"
                android:value = "com.android.deskclock.AnalogAppWidgetProvider" />
            < meta-data
                android:name = "android.appwidget.provider"
                android:resource = "@xml/analog_appwidget" />
        </ receiver >

我们知道一个Widget是一个BroadcastReceiver的子类组件。

上面我们只关注它的intent-filter的action,这个声明,表明这个广播接收者只接收intent的action

值为"android.appwidget.action.APPWIDGET_UPDATE"的广播。

事实是Widget本身也对这个做了判断。

AnalogAppWidgetProvider类代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/**
  * Simple widget to show analog clock.
  */
public class AnalogAppWidgetProvider extends BroadcastReceiver {
     static final String TAG = "AnalogAppWidgetProvider" ;
 
     public void onReceive(Context context, Intent intent) {
         String action = intent.getAction();
 
         if (AppWidgetManager.ACTION_APPWIDGET_UPDATE.equals(action)) {
             RemoteViews views = new RemoteViews(context.getPackageName(),
                     R.layout.analog_appwidget);
 
             views.setOnClickPendingIntent(R.id.analog_appwidget,
                     PendingIntent.getActivity(context, 0 ,
                         new Intent(context, AlarmClock. class ), 0 ));
 
             int [] appWidgetIds = intent.getIntArrayExtra(
                     AppWidgetManager.EXTRA_APPWIDGET_IDS);
 
             AppWidgetManager gm = AppWidgetManager.getInstance(context);
             gm.updateAppWidget(appWidgetIds, views);
         }
     }
}

 (1) RemoteViews

   文档的解释是:RemoteViews是一个描述了可以在其它进程显示View层级的类。View层级通过一个布局资源文件构造得来,RemoteViews类同时提供了些基本的用于修改构造的布局层级的操作。

  关于RemoteViews呢,我发现RemoteViews概述 这一篇博客讲得很不错,推荐去看。

(2)关于PendingIntent

 为也好说明,将上面的其中的两行代码改写如下:

?
1
2
3
Intent intent = new Intent(cotext,AlarmClock. class );
PendingIntent pi = PendingIntent.getActivity(context, 0 ,intent, 0 )
views.setOnClickPendingIntent(R.id.analog_appwidget,pi)

 上面的三行代码,第一行自不必说了。

第二行呢,需要对PendingIntent有一些了解。

顾名思义,PendingIntent即一个捎带了Intent的类。

我们知道Intent用于启动某一个组件。所以PendingIntent的静态工厂方法getActivity()

即是返回一个用于启用Activity的Intent.

因此显然PendingIntent如你所想像中那样还有下面的这些方法:

?
1
2
3
4
public static PendingIntent getBroadcast(Context context, int requestCode,
             Intent intent, int flags)
public static PendingIntent getService(Context context, int requestCode,
             Intent intent, int flags)

第三行,views.setOnClickPendingIntent(R.id.analog_appwidget,pi)

即是当点击桌面的时钟widget时(布局文件是analog_appwidget)时,启动pi所捎带的Intent.于是就会启动AlarmClock类,它是一个Activity.

关于PendingIntent的更多说明,请查阅文档,或者问下Google大人。

其它的三行代码就比较好理解了。

?
1
2
3
4
5
6
int [] appWidgetIds = intent.getIntArrayExtra(
                     AppWidgetManager.EXTRA_APPWIDGET_IDS);
 
AppWidgetManager gm = AppWidgetManager.getInstance(context);
 
gm.updateAppWidget(appWidgetIds, views);

(1)获得些widget的ID,注意是数组。

(2)获得AppWidgetManager

(3)使用AppWidgetManager的单例,及appWidgetIds,及RemoteViews的views更新此widget.

 

对于些widget类还有一个地方没有提及的就是:

?
1
2
3
< meta-data
                android:name = "android.appwidget.provider"
                android:resource = "@xml/analog_appwidget" />

这个是android中widget必须提供一些信息。

看看@xml/analog_appwiget便知,

推荐完全参数android中关于app widget的文档。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序邦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值