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

一,项目初看

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

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

  26个源文件

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

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

 

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

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

<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类代码如下:

/**
 * 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

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

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如你所想像中那样还有下面的这些方法:

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大人。

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

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类还有一个地方没有提及的就是:

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

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

看看@xml/analog_appwiget便知,

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

 

 

 

 

 

转载于:https://my.oschina.net/banxi/blog/78757

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值