博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
AppWidget实现机制分析--什么是桌面插件
阅读量:4139 次
发布时间:2019-05-25

本文共 3687 字,大约阅读时间需要 12 分钟。

    离开android开发一年半时间,终于又回到久违的android开发,与2011比,android系统更是搞得风生水起,市面上充斥着各种android系统的产品,从手机到电视,从医疗设备到汽车电子,魔多之眼在召唤,我又回来了,离开那与世隔绝小镇(无外网访问的一家it公司),来到中土世界,终于又可以在csdn写博客了。

    废话不多说,进入正题,最近两周查一个桌面插件(appwidget)问题,搞两周下来感觉对桌面插件的认识有了一个深入,全面的认识,有必要把它给总结一下,就从一个简单的textview的桌面插件为例开始讲起吧,这个例很简单,android应用开发解密和android sdk中带的demo都有,就是不断更新桌面插件textview的文本,很容易获取这样一个例子,你可以先下一个安装下,对桌面插件有一个直观的认识,本文不是告诉你怎么写一个桌面插件应用,而是阐述其内部实现机制。

   首先,我想我们得了解一个问题,那就是桌面插件是什么?先看AndroidManifest.xml中对一个桌面插件的定义

           
           
               
               
               
               
               
           
       

ExampleAppWidgetProvider是一个桌面插件provider类,它继承AppWidgetProvider,从AndroidManifest.xml中对一个桌面插件的定义中我们可以看出ExampleAppWidgetProvider实质上是一个BroadcastReceiver(广播接受器),从下面的类继承关系图我们也可以看出这一点:

但肯定它是有区别与一个普通的广播接收器的,试想,当我们添加桌面插件到桌面时有一个桌面插件选择列表,列表是有包管理器(packagemanager)加载出来的,packagemanager必须要知道它是桌面插件而非只是一个广播接收器,否则它是没有办法得出这个列表的,而决定一个BroadcastReceiver是否是一个AppWidgetProvider的玄机就是receiver中的meta-data定义,因为AppWidgetService服务启动就会加载所有桌面插件,所以我们就可以从AppWidgetService服务启动去剖析它

AppWidgetService->systemReady->loadAppWidgetList:

/**通过PackageManager加载所有系统插件应用*/    void loadAppWidgetList() {        PackageManager pm = mPackageManager;        Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);        //查询所有的broadcastReceivers        List
broadcastReceivers = pm.queryBroadcastReceivers(intent, PackageManager.GET_META_DATA); final int N = broadcastReceivers == null ? 0 : broadcastReceivers.size(); //遍历所有的broadcastReceivers,添加provider for (int i=0; i
关键函数是这个loadAppWidgetList->addProviderLocked->parseProviderInfoXml:

private Provider parseProviderInfoXml(ComponentName component, ResolveInfo ri) {        Provider p = null;        ActivityInfo activityInfo = ri.activityInfo;        XmlResourceParser parser = null;        try {        	//获取一个xml文件解析器,对应的xml解析文件是META_DATA_APPWIDGET_PROVIDER        	//这个meta_data指定的xml文件            parser = activityInfo.loadXmlMetaData(mPackageManager,                    AppWidgetManager.META_DATA_APPWIDGET_PROVIDER);            if (parser == null) {                Slog.w(TAG, "No " + AppWidgetManager.META_DATA_APPWIDGET_PROVIDER + " meta-data for "                        + "AppWidget provider '" + component + '\'');                return null;            }
上面这一段代码清楚地说明了我前面提到的问题
:决定一个BroadcastReceiver是否是一个AppWidgetProvider的玄机就是receiver中的meta-data定义,你可以看一下AppWidgetManager.META_DATA_APPWIDGET_PROVIDER="android.appwidget.provider",它是一个meta-data name通过它获取到一个xml文件资源,得到一个xml文件解析器,若没有定义这个meta-data显然parser==null,那就不能生成返回一Provider对象,这就是为什么普通BroadcastReceiver不会当作桌面插件来处理的原因

    继续往下,AppWidgetService会根据meta-data指定的xml文件生成一个Provider对象,先看一下这个xml文件的定义:

这个xml文件定义了一个桌面插件的配置信息,我这里对一些基本属性作了一个总结:

--android:minWidth:指定桌面组件的最小宽度,与AppWidget -ProviderInfo. minHeight成员对应

--android:minHeight: 指定桌面组件的最小高度,与AppWidget -ProviderInfo. minWidth成员对应

--android:updatePeriodMillis:指定桌面组件的更新周期,与AppWidget –ProviderInfo. updatePeriodMillis成员对应,这个注意AppWidgetService中作了一个限制,更新周期最少30分钟

--android:initialLayout:指定桌面组件初始化布局文件,与AppWidget –ProviderInfo. initialLayout成员对应,后面可为RemoteViews对象重新设置布局文件

--android:configure:指定桌面组件创建时候的一个初始配置activity,与AppWidgetProviderInfo. configured对应,可选。

遍历系统所有的BroadcastReceiver后,会在AppWidgetService中生成一个桌面插件应用列表mInstalledProviders,我这里把这个数据结构给描述一下,以便有一个直观认识:

前面xml中桌面插件配置信息都放在了AppWidgetProviderInfo中,当需要获取系统所有安装的桌面插件信息时,就可以调用getInstalledProviders获取,实质上就是获取mInstalledProviders列表。

   讲到这里我们再会过头前面我提出的问题,什么是桌面插件,是不是已经解答了?不然,我说到这里其实只是讲了桌面插件应用,说到桌面插件应用与桌面插件的关系你可以理解为类与对象的关系,桌面插件应用是静态的类型,桌面插件是动态生成的实例,为了便于理解我后面统一称为桌面插件实例,那我们继续解答什么是桌面插件这一问题。既然是桌面插件,那我们就从桌面入手,分析桌面插件是如何生成和添加的。

   欲知后事如何,请听下回分解。

你可能感兴趣的文章
nm: test.o: File format not recognized的原因和解决方案
查看>>
libtest.a: could not read symbols: Archive has no index; run ranlib to add one的原因和解决方案
查看>>
线程其实很简单
查看>>
别把&和nohup混为一谈, 根本不是同一个东西好不好 ------ 聊聊./a.out & , nohut ./a.out , nohup ./a.out &的区别
查看>>
守护进程(daemon)很简单------第一次玩setsid函数
查看>>
用linux下的daemon函数来玩守护进程------类似于nohup ./a.out &
查看>>
php和apache其实没有什么关系
查看>>
PHP的四种运行模式
查看>>
PHP——底层运行机制与原理
查看>>
so库又一次遇到 undefined symbol------ldd, nm, c++filt命令大显身手
查看>>
历经漫长的跟踪、排查、对比、推动和验证, 终于在8个月后,解决了这个bug
查看>>
linux下如何清空一个文件?
查看>>
小技巧:打印log时, 多了一个感叹号, 至少节省了1-2个小时!------又来说strings
查看>>
最近又遇到一个RST, 一眼就看出来了!
查看>>
为什么这个函数的返回值是-1, 浪费我10-20分钟? ------小心宏中return
查看>>
test二进制文件是否由test.cpp生成的呢? 怎么判断?------还是strings
查看>>
在Windows下搭建Apache服务器(试了一下, OK)
查看>>
Windows下搭建Apache, PHP, MySQL (试了一下, 靠谱, 写得非常清晰, 赞一个!)
查看>>
实例说明js脚本语言和php脚本语言的区别
查看>>
实例详解html的form表单和php的_POST数组,并用fiddler抓包来玩玩------走进Web、Server开发的世界
查看>>