`
dogasshole
  • 浏览: 839855 次
文章分类
社区版块
存档分类
最新评论

CMDN CLUB第14场:小米与友盟专家详解Android开发:

 
阅读更多

2月29日,CMDN Club第十四期活动在北京丽亭华苑酒店举行。本次活动是开春以来CMDN俱乐部的首场主题交流会,友盟Android SDK工程师徐仙明和小米科技MIUI系统工程师董红光为大家带来了Android资源访问与MIUI底层换肤技术的主题演讲。现场观众热情饱满,会场大厅内座无虚席。在CMDN俱乐部为大家精心准备的开场问答环节后,两位对Android资源访问有着深刻理解的工程师为开发者们带来了一场精彩纷呈的演讲。


图:CMDN Club第十四期活动现场

以下是两位专家现场的演讲实录:

主持人:不好意思,因为今天我们新年后第一次开放的活动,没有想到报名这么火热,我们其实已经提早关闭了报名通道,但是仍然现场大家还是对移动开发这个学习的热情还是很高涨的,所以现场要委屈大家了。等一下我这边有一些问题,我刚才想了一下,有奖励和惩罚的机制可以是这样,等一下如果是站着的朋友答对了,有机会有位子坐,如果错的朋友答错了要把座位让出来,这是准备了一些比较简单的问题。刚才开《非诚勿扰》大家有什么感觉?就是刚才选那个男嘉宾,我感觉主持人很不专业,大家有同感吧!他问的问题不觉得很浅吗?对于在座的各位来讲。比如说男嘉宾做的行业是什么行业?其实也没什么,就是大家等待的时候给大家一个娱乐机会。这个片子很有意思,就是想跟大家分享一下,但是看大家看了以后收效不像我想象那么好。

在座各位有多少是像他那样有笔记本、手机基本上离不开身,自己睡觉了,电脑还在工作这种状态可以举一下手?手机都是24小时工作。

因为我们这个差不多到时间了,我们这边简单做一个开场。

今天我们活动开场也是这边我会做一个整个活动的介绍。我这边也准备了一些关于Android开发的一些小的问题,我们这边也有奖品,这几个问题看看大家有没有可以答出来的。

Android代号大家知道吧?这些Android代号分别代表的背后的名字大家有谁知道的?比如说Android1.51.62.02.23.04.0,背后的名字是什么?

回答:有一个1.5版本的代号(英文)。

主持人:Android之父是谁?

回答:安德卢比。

主持人:谷歌发布的Android系统手机名称以及系统版本?

回答:

主持人:第一部Android手机哪一年诞生的?

回答:2008922号。

主持人:第一部Android手机是什么?

回答:G1

主持人:因为今天请了两位讲师分别来自小米和友盟,这两个问题是友情赠送给它们的软广告?M1是哪一年发布的?

回答:2010816号。

主持人:友盟是什么时候发布上线的?

回答:200910月份左右。


图:主持人现场主持

主持人:我给大家发的活动日程上面,其实把这几位嘉宾的微博帐号都有放上去,大家随时可以在微博上面给他们提问,或者是给我们CSDN这边提问,因为最后有一个非常非常充分提问和讨论的环节,供大家与嘉宾进行交流。

还有就是我们这个日程表还是一个调查表,希望各位在离开之前给我们做一下评分,有可能的评语也希望能听到大家的声音,我们以后的活动更加改进。这个调查问卷也是离场的时候提交到签到处就可以了,然后笔那边也有。

今天我们这个活动是今年开春以来第一次场活动,去年我们CMDNCLUB一共举办了12期,除此之外我们还有一个小规模的聚会,我们叫附带会,还有一个TOP30的一个聚会,这个是和我们CMDNCLUB开发者的沙龙同时都是在规划的。去年一共12期,这个主题涉及了方方面面,今年我们总的计划就是面向移动开发者这个群体有更多技术的交流,包括Android开发的、LSYPAPP我们都会有相应的系列讲座和交流的活动。

今天的活动我们也做了一些特别的安排,包括刚才开场给大家提的小问题,接下来是两位讲师,一位是Android系统开发的讲座,这两位都是在一线做Android开发的工程师,基本上都是他们日常的技术实践的总结。这两位讲师一个是来自友盟,一个是来自小米的,接下来就是我们另外还请了球球搜工程师,还有原来在互联网电视方面的刘金瑞,请他们进行讨论。各位有问题可以通过微博问我们,或者大家可以写纸条递交到主持人这边。

现在我们先把话筒留给第一位讲师,来自友盟的徐仙明。徐仙明:会做一下自我介绍。他也准备了几个问题,抛给大家,看看大家能不能答对,大家欢迎一下。


图:友盟工程师徐仙明在讲解Android资源访问机制

徐仙明:我一进这个屋子就感觉到大家今天所带来的热情。非常感谢媛媛的介绍,我是来自友盟的徐仙明,我在友盟主要是交换产品,在Android客户端SDK的开发。今天我希望给大家带来关于Android平台上怎么样管理资源。刚才谢谢媛媛给我们插播的软广告,接下来我简单介绍一下我们公司。

友盟主要是针对开发者提供一些平台式的服务,我们提供一些统计分析还有开发工具,还有一些应用联盟这一类的SDK,大家可以用。可能在座很多的都是开发者,应该多多少少会有接触,我们同时提供一些数据报告,我们还有一些专业的跟移动开发相关的一些沙龙,欢迎大家参加。

在讲之前这个是我今天讲座的一个提纲。首先我介绍一下什么是资源,就是说在Android里面资源是什么东西,然后接下来简单地讨论一下都有哪些资源,资源的种类,以及如何去定义这些资源,然后接下来我们讨论一下在Android系统都提供哪些资源,就是我们这儿所说的系统更多的是指在Framework提供的资源,包括我们应用是什么资源,以及怎么处理这些资源,讨论完了以后我跟大家探讨一下一个比较有意思的话题就是换肤,对于应用以及对于系统怎么样更换皮肤,换肤这个事情在国外不是讨论的特别多,但是在国内用户对于皮肤就比较感兴趣了,比如说有兴趣换一个不一样的界面。

到底什么是资源呢?在Android里面资源可以统称为包括图片、包括MP3一类的声音文件以及其他的很多文件,我们今天的话题主要是讨论跟UI相关一些东西,所以我把我的话题范围缩小到描述UI这些元素上面。比如说我们图片,比如说我们应用的图表还有布局文件,我们的SDK里面包含哪些部分,我们的字符串,还有一些RAW,其中很重要一部分是通过XML形式描述这些资源。我个人认为谷歌设计Android系统的时候,他把界面的设计和代码逻辑分离开来,界面设计通过XML的形式来描述,后具体的程序的应用逻辑,通过代码来实现,所以他把代码和逻辑分离开来,其实界面更多是一个偏向UI工程师的一个工作,逻辑更多的是一个程序员所做的事情,是码农像我这样做应用的逻辑开发,这个和我们外部开发非常类似。我们外部开发会有前端工程师,怎么样写HTMLCSSJS,我们的后端工程是用GSPJAVA去实现它。

Android里面有什么语言呢?就是你能够发现有一个RES的文件夹,这个文件夹就是里面有各种各样的资源,这个大家很熟悉,我不多说了。这儿我想讲比较特别的是一个叫values,如果大家看Framework的源代码,会发现Framework有一个volues—,这个东西可能跟语言相关,就是测算系统用中文还是英文,有可能跟分辨率有关,有可能和版本有关,所以当我们去开发一个应用想把这个应用做的比较普市,能够在不同样式的手机上都跑起来的话,我们可以针对每种不同的手机配制做资源。

简单打一个比方说我们的应用的用户既有中文用户也有英文用户,我们这个应用对于英文的用户他打开的时候他想看到这上面的字符串是英文的,然后我们就可以把这个英文字符串放在values—下面。中文的我们可以建一个values,我们刚才说到Android里面是用XML形式来描述的。XML是用来描述数据的,所谓描述数据无非就是说我这个数据有一些属性,然后会有一些值,就是说它会有一个属性和值的一个结合。然后在Android里面就很好的利用了这些特性,因为Android里面我们所看到UI界面的东西其实就是标识属性。对于XML就是有一些限制,对于attr—values里面可以包含那些属性,至于具体属性的值会在哪里呢?就是我用它的时候存储数据的时候我会用在layout或者是style。我们的这些值在Android里面一些简单的类型,比如说我的E.g.TextView

比如说E.g.TextView里面有一个小组件,TextView在这个文件下面,这是我从Framework源代码里面找出来的,它就描述了TextView的属性,在这里面它所拥有的一些属性,比如说这个叫BagText,下面就可以找到Text。这个过程是怎么样绑定的呢?右边就是TextView,比如说aTypedArray,就是通过这个可以访问这个数值。

我关于资源访问这一部分在Android整个性能架构里面处于什么样的位置呢?首先我给大家设一幅图,这个图是所有做Android开发的人见过的,几乎是跟Android相关的讲座会设计的一张图,我这儿不可避免用这个图。这部分就是跟Android有关的,下面这部分是LinuxAndroid没有关系。主要这部分是AndroidRUNTIME,这个是Java的一些语言库。对于这部分就是我们在做Android的开发中会用到的,比如说Framework.jar,还有一个Framework—res.apk,这个就是我们说的Framework所提供的资源包,上面是系统所提供的这个类的一些文件。对于我们核心的跟资源相关的一个组件是叫ResourceManager,通过这个访问一些文件系统。


图:友盟工程师徐仙明在讲解Android资源访问机制

我们回头看一下源码中的位置,左边是我们拿到的SDK的文档,里面显示我们所拿到的类包,我们几乎所有跟Resources,它的源码也在下面会有。在这儿我给大家推荐一个网站,其实大家有时候会想到说去看一看Android的源码,说把Android下下来比较大比较麻烦,Platform可以在上面看一看。右边这个就显示了我跟资源相关的东西都放在哪儿,就是Framework系统提供的Resources所提供的一些资源。

我们谈到系统资源,接下来说一下应用所提供的资源。大家有谁知道我们从网上下载一个应用,就是下载了一个APK之后,我们点击安装的时候,系统会做哪些事情呢?当我们安装一个APK的时候不管是从网上下载还是从手机下载下来的,它会做一些检查,比如说对你的权限一些检查或者怎么样,但是本质上过程是非常简单,就是说它就把APK复制到你目录上。

这是我们自己开发的APK,对于系统所使用的APK,比如说一般Android操作系统出厂之后会带一些系统级别的应用,比如说打电话的应用、发短信的应用这都是核心的应用,会放在Syston下面。如果有的下付费应用会看到这个应用。

对于一个具体的APK里面包含什么内容呢?这张图解释了APK的结构,APK本身是一个很简单的文件格式,它只是一个压缩文件夹。我们可以通过解压压缩文件夹把这个APK解压出来,首先有一个METAINF,这就是APK的原数据,可能我们打包APK的时候会有一些签名,签名的一些信息在这里面。还有MANIFEST这个大家很熟悉了。还有一个RES目录,这个里面有图片的资源,Layout也会用到,如果你的应用有XML也可以用。这个里面其实和你的工程目录还是有所不一样的。这个ARSC在网上关于格式的描述很少,可能这个本身没有开源,具体我也不太清楚。你可以通过AAPT可以把这个东西档出来,D表示档,把RES相关信息档出来,就可以看到和APK的东西了,每一个APK复原了一个值,对于系统资源它都以01开头,对于应用资源他都用07开头。对于CLASSES.DEX这个是W虚拟机专用的格式,本质上就是java变异之后的一些文件,这些文件会进行一些优化,生成一个CLASSES.DEX。这些文件在你安装的时候,实际上系统会把这个文件抽出来解压出来以后放在我的DALVIK—CACHE里面。这个目录里面有很多DEX的文件,如果说我要打开一个应用的时候,系统会做什么呢?打开一个应用的时候,系统加载这个系统对应的类,如果这个系统加载这个系统对应的类的时候他去APK的时候需要解压,这个效率比较低,所以他先会把这个DEX的文件放在这个上面,然后我加载起来就会比较快。

刚才讲到系统的资源和应用的资源,有人就要问了,我们要知道其实在Android里面每一个应用都当做一个进程来处理,但是每一个应用都可以去访问Framework的资源,但是如果这样做,岂不是很带内存吗?就是我对不同的系统启动的时候用不同的资源,只有这个资源共享才能减少我内存的浪费。对于W虚拟机到底是怎么样做到,怎么样共享Framework的资源。首先介绍对于应用的进程怎么启动。

首先系统启动以后会执行这个RC文件,这个ZYGOTE翻译过来就是一个卵,可以孵化出很多的其他进程,这个词非常非常形象。我们看细胞受精了会分裂,一分二,二分四,所以这个ZYGOTE也是非常类似的概念,这个是祖宗,它会本身FORK出一个SYSTEMSERSVER进程,ZYGOTE进程在启动的时候同时会加载Framework前面定义的类,还有加载那个资源,但是实际上它并没有说把Framework所定义的所有的资源都加载进去,因为对于Framework来说这些东西会比较大,而且Framework里面定义的资源和类并不是每一个应用都会用到的,他可能会把这些应用可能会更常用的独立出来,资源也是类似,就是说在这下面有一个表明了系统启动的时候加载了Framework的资源。当我一个应用启动的时候,ZYGOTE就会把自身FORK一遍,复制之后再去创建我应用对应一个进程,加载应用的一些代码,开始应用的运行。

我们看一下这个图,这个图本身是从有一本书叫Android内核剖析截取过来的,我们可以看DalvikVm它启动的时候创造ZYGOTE进程,ZYGOTE会加载Framework共享类和共享资源,同时它会通过开启Socket服务端,每一个应用会创建对应的进程。我们会发现说,其实每一个进程它都认为自己有一份关于Framework共享类以及共享资源,但是实际上他们存在一段物理内存空间,我在整个物理内存空间里面只有一份关于我系统级别的资源,而当我从一个新的进程出来以后,我对于每一个内存没有修改我们可以共用一个内存,但是Framework类和资源是只读的,而且对于Android操作系统设计之初本身没有硬盘的虚拟内存换进换出机制,所以这一点对于Android来说非常重要,它节省了很多很多内存。

我们看一下这个过程具体是怎么样实现的呢?我摘抄了几段源代码出来。当我启动一个应用的时候,ZYGOTE所有应用的祖宗,它会复制自身,创建一个新的进程,就是PID。这个PID是运行在子进程里面加一些对应的类和资源就开始子进程的界面了。我们进入子进程以后,我们就开始应用运行了,比如说我要打开一个APK,他会调用我们这个APK对应的类,会调用这个入口函数,在入口函数里面会调用比如说我应用启动打开的时候我能看到我应用的界面,从而我这个应用对于用户来说就启动起来了,就开始运行,在我应用的进程空间里。

对于具体应用来说它怎么样访问资源呢?其实有两种方式,一种是通过Context,相信很多人用过Conext.getResources,在应用的时候它会调用一个函数,它会有一个管理资源的搜索中心下面,对于应用来说就可以访问这个资源了,就是在SDK文档里面画的图。这个是访问应用内部资源的时候这么做。我还可以访问其他的应用资源,其实大家可能会有疑问说,不是说每一个应用都有一个进程,每一个APK对应有一个进程,这句话听着貌似是正确的,实际上你可以使得不同的APK放在同一个进程里面,就是我们下面所讲的。

这个有什么意义呢?就是说我们做一些资源放在另外一个APK里面,安装别的APK这个应用可以通过,可以访问,我们可以把我们的皮肤放在别的APK里面,我们可以从网上下载APK,从而访问那个APK那个资源,从而达到换肤的目的,换肤也是大家比较感兴趣的话题,我先抛砖引玉一下。

先说对于应用级别的换肤,一种是说我简单的内置,非常非常简单的逻辑就是说我可能是说用户选择了设置了我使用第一种皮肤,皮肤无非就是图片这一类的资源,就是说我可能背景图片改一改,样子改一改,然后如果用户使用了第一种皮肤,我就使用第一张图片,如果用户用第二种皮肤,我就用第二种图片,所以我只需要通过一个简单的代码逻辑去实现,这要求我把这些资源都放在APK之内。另外一种方式就是说我这个皮肤外置可以下载,我可以复制,也可以动态替换。两种方式,一种是通过APK的方式,其实我们刚才在前一张里面讲到,不同的APK可以放在同一个进程里面,我在一个进程里面访问资源,就是说我这个资源必须在我这个进程里面,如果在别的进程里面就需要通过APC通讯很麻烦的方式。我把我对应的资源放在进程中,Android本身提供这个东西,如果我有两个APK,我在他们AndroidManifest.XML文件中就可以访问资源了。

我们看这一段代码可以通过一个应用访问另外一个应用的包名,那个包名APK主要存放皮肤资源,我就访问这个包,通过这个包可以得到另外的包的资源,所以可以把皮肤的资源放在另外一个包里面。我们现在在市场上见到很多的桌面应用程序,有的就是通过这种方式来实现的换肤。还有一种就是说我不用APK,我就普普通通的,比如说我要一个Skin目录板,放在这下面,我都是一直在这个下面去取资源,如果下面没有我要的资源,就调用我的默认资源。当用户换了一个皮肤的时候,这个应用就会下载新的皮肤文件,同时把原来的文件替换掉。我们所见到比如说墨迹、还有搜狗输入法,这些应用都是通过类似于这种方式去实现换肤功能。

我们看一下墨迹到底是怎么实现的。墨迹会有一个工具的页面,有一个皮肤小库,比如说这个里面有一个情人节的皮肤,我看一下我的目录文件发生什么变化呢?结果发现在SDK里面墨迹建立了一个文件夹,下载一个叫103.ZIP这个资源包,他把这个ZIP资源包解压Skin103这个下面,这是皮肤包含的资源文件。我定义这个文件名一定要跟系统默认的一模一样,我可以比系统里面的少,如果我找不到这些系统资源,可以到系统默认里面去找。

这是针对应用级别的换肤的方案,对于系统皮肤就是在网上找一些方案,相对来说比较复杂,对于系统来说很难去写一个APP,给系统设置什么主题这是很难做到的。我们想做到更换系统主题,就是涉及到修改Framework源代码了。一种方式我们简单谈到系统访问资源的时候是通过AssetManager这个类,提供Frameworkres.apk,如果我们要更换系统资源的时候可能是说去修改这个函数使得它去别的地方找资源,这样可能达到一个系统主题的目的,接下来MIUI工程师会更详细讨论这个问题。

另外一种方式因为我们在应用这个级别去访问资源的入口都是通过这个类来,这个类就是Java是通过一个类,如果我们想换系统主题,就让这个函数查找资源的时候,别让他去找Framework下面的资源,第一是01开头的话我们就返回,可以复制到我们自己的主题上面那样也可以。董红光会更详细解释这两种技术。我今天的演讲就这些。主要是讲了在Android系统怎么样访问资源,系统的工程怎么样共享资源的,对于系统和应用它的资源访问有什么不一样,以及有什么相同之处。后面谈了一下关于应用和系统的换肤,这个是我今天所讲的全部内容。谢谢大家!大家有什么问题吗?


图:提问获赠《程序员》

提问:我是个初学者,刚刚您讲到他如果不同的进程访问同一段资源的话可以放在一个共同的物理内存里边,我想问的是如果这两个进程同时都访问这个资源,然后都有更改的需求,是不是会有一个锁或者多份COPY的情况?

徐仙明:这个问题非常好,因为刚才画的图下面存在物理内存,其实是共用的RES或者是CLASS文件,这个类决定是它是一个只读的东西,所以不可能在进程里面访问。操作系统提供了一个COPYRES的机制,就是有人去改,他会做拷贝,就是每一个进程在自己的进程里面操作,其实你改变是改变自己的物理空间,至于你所说如果他们去修改这个锁可能是更底层的一些问题,跟Android开发关系不是很大,当然可以了解一下底层的实现。

提问:比如说两个进程里面都有更改,在他自己的内存内部生成这个更改会合并吗?

徐仙明:不会合并,就是每一个进程里面都有一个自己的COPY,他不知道这个东西是共享的,对于内核知道,但是对于进程是自己的虚拟空间里面操作,所以他操作的是自己的资源。所以说他会有两份COPY,并不会合并它。

提问:我想问一下刚才两种共享资源的方式,有一种换肤是用ZIP,你后面的一些文件到底怎么用?

徐仙明:比如说因为文件是设置你的背景,就跟你在网上下载一个图片共享是一样的。

主持人:接下来有请小米的工程师董红光。


图:董红光在阐释“小米一代与一袋小米”

董红光:谢谢大家。可能有的人没有吃饭,还有很多人站着,我就长话短说。我先简单自我介绍一下。我叫董红光,是北航本科毕业的,所以今天来到北航的地盘感觉信心爆棚了,很高兴认识大家。我现在是在小米担任MIUI系统工程师,我现在主要负责的是MIUI主题这块,就是被很多人称为最酷最绚这一块。很多人对如何换肤很感兴趣,刚才友盟工程师说了是抛砖引玉,我们这个也是抛砖引玉,我们做的可能相对比较浅,可能还有更多深入可以挖掘的点,所以今天跟大家分享一下我的这些东西。然后希望能有人受到一些启发可以做出更酷更绚的产品。

我今天的主题是MIUI主题风格,这是一种Android系统换肤工程的设计思路。

说到主题首先大家要想到主题是什么?可能这个概念对于大家来说应该都不是很陌生。比如说QQQQ的主题,WINDOWS可以换自己的主题,比如说QQ有什么红橙黄绿青蓝紫,各种各样的主题,甚至论坛有的普通主题、文艺主题等等这种东西。这就是我们常说的主题。主题这个东西在手机是什么样的呢?我们先回顾一个系统。

这个是塞班系统S60的界面,我现在随便在网上下的主题包截图,我们看风格完全不同的,这个是被很多人称为明日黄花的塞班系统。

我们现在可以回顾一下比较火的系统现在有的,一个就是Android,一个是IPHONEIOS,这些系统他们支持不支持,首先说IOS答案就是不支持,如果你要越狱还是可以做到这一点。Android支持不支持?Android其实它标称是支持的,它怎么支持的呢?它实际上再一个XML声明写一个Style,然后在应用程序里面制定你这个主题用到什么样的Style,这个是程序显示指定的样式,就是我这个程序用Android4.0等等一些主题风格。它能更改哪些东西?一般来说可以更改字体、颜色、长宽、间距等等这些东西,实际上真正的主题是不是这些,其实不是的。一会儿可以继续说。所以说这个地方看到其实Android原生提供的对于可替换的资源类型是十分有限的。

这两个截图就是它不同主题下的展现的方式。右面那个图已经参杂了我们MIUI的元素了,比如说上面这个图表,这因为是小米手机上截屏,这个是原生的,其实它一般来说就是换一些现代颜色、背景的颜色等等这些,其实图片都可以不换的。这个就是我们目前市场占有率第一大的操作系统可以做到的效果。

刚才我说到这个是不足够的,回过头来我们说一下主题是什么东西?主题我自己认为的一点就是说所有影响用户界面效果的属性的集合都称之为主题。比如说音效、图片、切换动画都算,这些东西当然了之前提到的字体、颜色、长宽、间距等等这些,另外最重要的就是图片,其实我们看到的一个程序给大家一个整体的感受,可能更多就是它的一些背景图,按钮的样式,所以说图片这个地方是非常重要的。当然很多人是做程序开发的,大家也都懂,我们做程序开发有一个通用的办法就是把一些图片资源和样式称之为资源,在Android中刚才友盟工程师讲的非常透彻,实际上Android也有资源,实际上在我们认为系统和程序称之为资源。之前Android的一些应用程序本身是由开发者去制定的,我要用4.0,我要长成一个白色的样子,或者是黑色的样子,实际上真正需求远远不止这些。比如说我是又宅又孵的,你设计出来是比较清新的风格,我可以换一个风格搭配我的使用。第二点就是即时生效,就是说我如果换一个主题,不能说等很久,比如说Android系统是待着没事儿杀进程,这样的用户体验是很不好的。

接下来问题来了,就是怎么做?这个怎么做不是指主题包本身怎么做,因为平时我跟大家介绍我的工作的时候可能大家都秽闻你在做什么,我说我做主题,他们说你不是学计算机的吗?怎么回过来做美工了呢?其实不是。怎么做?有两方面,一个是主题报告怎么做,我们怎么样画出漂漂亮亮的图片,我们怎么样有各种各样的风格。另外一个方面就是我们系统如何支持他用了这样的主题,在我们的系统之上我们就能把他的图片显示出来。

首先我们就要看一下Android的资源管理机制。其实我写这张PPT的时候也很纠结,因为我不知道在座的同学们Android相关的知识多与少,因为可能有的人相关的知识很多,我介绍这些其实还是挺浪费大家时间的,不过后来我发现原来在我之前还有一个讲师,就是友盟的讲师先给大家做了一个快速的入门,我就假设大家是五十分钟精通了Android资源管理机制了,我就简单过一下,可能一些我们主题可能涉及到的一些点。

首先第一个就是资源的类型,刚才也提到了,资源的类型比如说DrawablelayoutstylestringCOLOR,通过R.什么什么东西,系统同志RES这个类拿到你需要使用的东西是个颜色还是一个图片等等的。平常我们用的时候就是用Context.getresources这一类的东西,实际上它的底层就是这个。

回到刚才的问题就是我们怎么去做?首先想到第一个思路,刚才说了这么一大堆东西,之前友盟工程师也花了将近一个小时的时间讲我们整套的机制,大家首先想到的是什么?就是复杂。相当的复杂和麻烦,我第一个解决方法可不可以绕过这套复杂的机制,答案是可以。就是直接读取外部资源文件,你这一面是用R又是用RES什么的,我不用这些东西,你给我提供了Drawable就可以读取,比如说你写了一个按钮,按钮的背景你需要运行初始化的时候去传一个图片或者是传一个颜色。其实这个缺点就出来了,就是说满屏幕你为主题、你为你的皮肤都要写类似的代码。

看一下它的特点,首先第一点就是主题包格式非常灵活,就是说这个格式完全你自己去定义,你愿意定义成一个文件夹放所有也没问题,你愿意定义成自己压缩的格式也都没有问题,反正解析的操作是你自己来做的。

第二点刚才我也提到了,就是你自己需要手动管理,你在你的程序中你要去设置。不过它也有优点,它的优点就是可控换肤。比如说搜狗的输入法是支持皮肤的,他的皮肤可能只允许你换一部分东西,如果不是这样的话,我把搜狗的LOGO换成百度了,主题应用完了之后就成了百度输入法,这肯定不是搜狗想看到的,所以这个有很大的优点,就是LOGO不允许你去换。


图:董红光现场讲解PPT

下面一个缺点是什么呢?就是没有办法给系统和其他的程序进行换肤,为什么这么说呢?就是因为所有的代码都是写在你自己的程序中,你不可能影响到系统,也不可能影响其他的应用程序。所以最终我们觉得这个东西只适合APP级别的换肤。

说了这样一个思路,至少我们已经打开了一点思路了,我们再回头分析一下它。我们看到这么多东西,有什么东西可以改进,首先一点我们看到这个手动解析资源,可能大家不是很明白这是什么意思,其实Android的那一套资源管理有自己的组织方式,然后它也提供了相应的解析逻辑,如果你自己去指定这个主题包,你自己要去解析这个逻辑,大家说没有问题,反正我自己定,但是有些问题,比如说Android最常见就是可以给不同的机型运行程序的,可能有的机型分辨率很高,有的机型分辨率很低,有的及其DPI很高,有的是DPI很低的,这样Android提供了一套机制就是说在Drawable下面挂了很多的目录,这些目录分别去放为每种分辨率设计的它的图片,因为你可能高分屏要设计质量比较高的图片,低分屏要设计质量比较低的图片这很正常。所以这一部分东西,Android会帮你去做这些事情。比如说你是在一个低分屏下,但是你的程序并没有给低分屏做图片,不代表它压根不显示这个图片,Android会给你算,会优先读这些资源,这些事情Android已经默默帮我们做了,我们想抛弃它没有这么简单的。

我就在想,能不能把手工解析这个地方去掉,我让Android还去帮我做这个事情,但是我不让他帮我管理加载哪些资源,这就是我们的思路二。说来简单,但是我们需要找到技术支持,搜遍了SDK的方法终于找到了一个,就是PackageManager,比如说购物桌面,我没有看到它的代码,我觉得它的机制是这样的,就是它可以读其他第三方的一些为它做的一些主题,而其他第三方都是一些APK格式,装到你的系统中,它会通过这个方式,把第三方的资源全都弄进来,他所用的就是RES,而且这个东西并不受签名的影响,因为它是可以跨不同的作者、不同的签名去访问的。

拿到了它之后,我们成功一半了,因为拿到了其他人的RES,我们可以拿GETDrawable等等的,接下来就是我们自己去做的,如果有主题文件那么我们就去那个里面去找,如果没有主题文件我们就从我们自己里去拿。它的相对于前一种思路的优点出来了,首先它的包就是APK包,它的缺点就是制作门槛比较高一点,因为APK还涉及到打包、签名一些操作,可能一般的平面、UI设计师他们不会做这些东西,他们最多打一个技术包,系统会帮你解析这些所有的资源。

下面这些特点其实和上面的差不太多,手动管理、可控换肤,而且它也没有办法给系统和其他换肤,所以最后这个东西只是适合给APP级别做换肤。

其实我们努力了半天,想了两种办法都没有做到给系统级别或者给其他的APP换肤,怎么办?有办法。首先想到的一个就是偷换概念,什么叫偷换概念呢?你帮我买一个小米一袋,我就给你拎一袋小米回去。实际上他管我要的是某一个资源ID,但是我假装不知道,我给他是另外一个,这个地方大家可以很容易想到,为什么我们可以做?资源是有规律的。O1开头的都是系统的ID,这样我们就可以做一些事情了,就是说我发现如果是0X01开头,我把这位从1变成7,我自己做一个APK,然后里面它的ID和这个一一对应的,只是前面这个开头是不一样的,这是可以做得到的,这样别人给我要这个资源ID我就给他返回另外一个。而这个是要和PackageManager合作的。它的特点就出来了。下面就是自动管理、自动换肤,这个时候你的应用程序不需要感知我怎么样拿皮肤相关的一些东西了,我只要管RES去要,我要某一个IDRES,这个时候我自己去解析一个映射文件,我把他的ID映射到那个文件资源ID,所以可以实现自动换肤。

有了这样一个特点之后,就可以系统换肤了,其实我们改的也是系统代码,因为我们是做ROOM的,所以有了Android的代码还是可以改一些东西的,所以我们改的是RES。但是它也可以为其他的APP换肤,但是比较麻烦。还是回到R的机制上来说,R本身是由APP编出来的,系统的还好,系统在编的时候还会出现一个文件囊,他会把系统常用暴露出来的ID,这样你影射很好影射,但是如果你没有这样的ID,你增加资源和删除资源这个ID会变的,变了就映射错了,你明明是为0X01做的,但是这面0X01已经变了,这个有很大的风险。在资源ID变化的时候它的解决是很麻烦的。

另外一种就是资源缺失的时候,我们做了什么?就是把这个由1换成7,读完了以后重新返回一个数据,你原来的资源在新的主题包没有怎么办?你可能判断一下这个主题包有没有,有的话再返回这个,没有你就返回原生里面了,所以还要做一些额外的处理。

这个看起来是可行的,但是有很多麻烦的地方,而且为第三方APP换肤麻烦这是我们当时考虑到最重要一个缺点,所以说我们把它砍掉了。砍掉了之后怎么办呢?再往底层走。

再往底层走RES这一种方式不行,下一就是AssetManager,我们也看了AssetManager的代码,它有一个AddAssetPath,每一个程序启用的时候,就是用它路径实现过来,然后把自己的RES加进去,一般是这两个,当然额外也有别的情况。

比如说这样一个东西以后我们想到了,对于系统换肤来说,第一个特点这个主题包必须是APK的可以自动解析,可以自动管理,也可以实现自动换肤,这个最主要一点就是可以为系统和其他的APP换肤,就是我直接把原来的APK换掉了,任何一个系统或者是一个APP资源都是存在APK里面,我把APK替换了。

这里也有一个很重要问题,就是我在最底层整个集合换掉了,当你主题包资源缺失的时候怎么办?你找不到了某些地方就会变成一个空白,显示不出图片,有些地方直接抛异常了,这是我们大家不希望看到的。怎么办呢?实际上两种办法,一种办法就是资源缺失在做主题的时候先把之前所有的这些全都解开,开开之后我需要哪一个就用哪一个,全部打包过去,这个对于主题包的负担很重的。第二个办法就是我在最底层做,在上层也要做,我一旦资源缺失了我再到新地方去找,这个改动是很大很大的,因为上层的话不会判断同样的ID怎么去处理了,因为你可能他俩虽然是不同的APK,但是他们两个同样一个资源共用一个ID,这个时候系统处理不了,我们还要进行各种各样的处理,很麻烦。这种办法也不是很好。有没有更好的办法呢?

刚才说的是对整个资源包进行一个重新设计,接下来就想我们可不可以为单独某一个文件进行设计,实际上我要的是一个小米手机,我回头其实给了你一个大米手机,你这面其实要是人的话肯定不行了,是你坑我,但是实际上程序是可以的,因为程序它是非常信任这个Framework,所以在这个地方我要还是要原来的东西。我要了原来的东西,我在RES这一层,我直接不读APK,我到一个新的地方去读,这是在思路三和思路四之间一个折中。思路三是我改你的资源ID,思路四就是我不改你的ID,我把底层全改掉,现在这个折中办法出来了,就是我不改你的ID,但是我对你的底层进行管理,你可以自己定一套格式,所以既支持手动又支持自动的解析资源。它的特点就是自动管理、自动换肤,同时也可以为系统和其他APP换肤,因为所有的APP都要通过RES这个入口去访问资源。这个时候资源一旦缺失的时候,它的解决方法非常简单,因为我们在RESGET的时候GET不到我就什么都不做就直接返回。

这个是我刚才提到五种思路,这个地方列了一个表,大概对比了一下。第一排就是主题包的格式,这三种是APK,这两种是任意,也可以用APK的方式,APP对显式管理,前两种是是,后两种是否。系统换肤前两者不支持,最后三种是支持。

MIUI怎么做呢?其实刚才也分析了半天了,给了大家五种解决方法,我们采用思路5,重定向资源文件路径,就是把入口里面的逻辑改了,我们的入口就是RES类,我们更改它,截获所有资源的请求,首先在我自己里面判断,如果有就返回,如果没有交给系统去做。我们的主题包是自定义格式了,我们通过一些优化做一些处理。我们还是为了方便起见,我们每个安排APP一个资源包,主题包没有资源就返回原生资源。

这是很简单的一个结构图,APP通过RES这是我们改过的接口,现在这个地方加了一个HOOK调动我们自己的代码,背后相对有一套逻辑,但是这个地方只有一行,加进来我们去判断是不是存在,如果存在就这一个地方去找,找到就返回,如果不存在就交给原来的。

刚才说到主题包,分析一下这个主题包格式,主题包格式不是APK,但是实际上我们为了方便主题方式有点类似,我们也是用ZIP包的格式,但是不用签名也不需要变异相关的操作,很简单就是一个ZIPZIP里面是一个局部项目集合,这个局部项目很多了,有一方面是大家经常用到的一些东西,比如说图表、壁纸、来电铃声、开机动画和音乐这些东西,这些东西走的不是那些机制,这些东西都有自己独特的方式,如果有时间我可以继续给大家讲。其他的一些资源就是我们刚才所提到的比如说你给QQ换肤,这个是以APP为单元组织的,每个APP是一个小的主题包,这个主题包它也是一个ZIP格式,它里面包含了哪些呢?一方面就是Drawable,就是刚才说到的图片,它的层次结构也是一样的,Drawable下面如果你给高分屏做了一些东西,你就放在Drawable—HDPI,这个也是为了让我们通过Android一些东西去获取,不需要自己去算,考虑到这个问题。

刚刚提到颜色等等都统一在THEMEvalues.XML,这个也是考虑到主题制作者对这一套结构完全不感冒,他们觉得怎么简单怎么来。很多人原来就没有编程的知识。

我们看一下THEME—Values.XML是什么东西。书写方式与AndroidCOLORS.XMLdimens.XMLStrings.XML,对于程序制作者来说是完全透明的,我们只是解析它做一个替换。

刚才提到这一个,可能如果要是做Android开发比较多的有一个问题就是说其实你这个东西局限性很大了,比如说你REFERENCE类型是不支持的,你也不支持多值属性,比如说我把一个ARROYSstyle里面的数值替换掉这个也不支持。我想把自己设计一个风格支持不支持?不支持。我们考虑到主要是一个BAR原则,大部分APP视觉的元素和主题的元素大部分定义在刚才说到的这些地方,比如说COLOR这个是比较常用的,另外就是图片,所以我们做了一些取舍,反正这个地方也是可以做的,只是说这个地方的代码不能拿Android自己的代码了,我们可能还要自己重新写,重新解析。

大家说你不支持多值属性,layout你最得支持吧?我这个布局、大框架、上面是抬头、下面是按钮,这个我们也可以做到,但是我们不支持。为什么不支持呢?还是涉及到一个安全的考虑。比如说他随便调整了一个位置,他把确定和取消给换了一个位置,可能大家觉得没什么,但是使用者会觉得特别扭,你不小心点了弹出框架你习惯性点右边就不好了,所以这个地方利用不好就会有很多潜在的风险。比如说他改了一些拨号键盘的位置,1234567890完全错开了位置,程序就没法用了。

说到刚才主题包的格式以及它的局限性,接下来说主题包怎么解析。主题包解析两大部分刚才也提到了,第一部分就是独立的元素,图表、字体、壁纸、音效、开机动画等等,这些有Android的接口就可以像图表、壁纸、音效,但是有的得改更底层的代码,比如说字体和开机动画这些东西。

我们看其他的APP包,我们一次性解析THEME—VALUES的所有值,为什么一次性把所有东西都加进来,也可以做到你用什么就加什么,但是一个正常的主题包为一个APP设计的更改的样式不是特别多,所以我们一次性解析了可能提高效率。

接下来就是Drawable,图片不能一次性都解析,这个地方跟Android是一样的,它只有在使用的时候才去进行加载,加载之后Android的方式实际上在GETDrawable读一个图片的时候,它有一个缓存一个表,它会看一下这个地方是否之前已经加载过了,如果没有加载过他再去加载,实际上我们这个地方就是,如果没有加载过,我们先用我们的东西去加载,加载不到再用他的去加载。加载完了之后他会统一把这个加载之后的东西放在系统缓存中,下次再访问的时候就会很快。这是他的机制我们充分利用了他的机制。当然我们也可以在系统缓存之上自己去建立一套自己的缓存机制也是可以的,但是当时我们觉得没有必要的。

刚才说到的一点就是每个APP实际上每个都是ZIP包,ZIP包打开非常耗时,所以我们对于每个程序来说它其实用到APP包是有限的,用到的资源包是有限的,我们会有一个文件池,这个文件池会存他所有需要用到的APP包的距离,这个也是最近经常使用的方式这样一套逻辑,如果不常使用的东西就直接释放掉了。

刚才说到了那些东西大家可能觉得说我们整个主题的功能应该基本上可以满足了,其实也差不多可以满足大部分功能,但是还有一些点是需要考虑的,首先第一个点就是局部更改全局样式,这是什么意思呢?比如说短信里面经常用到系统的一些资源,它的列表它可能用系统的一些资源,但是我为短信专门做了一个皮肤,这个时候我不希望把系统整个所有的列表全都换掉,如果都换掉因为我只给短信做了这点东西,你把短信换了,其他程序就不搭了,我们引用了一个OVERLAY机制,还有主PACKAGE这个概念,主PACKAGE本身是一个主题包,这个主题包中如果有什么东西我是系统或者是其他第三方APP,但是我不希望他们用到,我直接定义在这里面,这里面是一个目录,然后用同样一个结构,然后我们会优先去看,他自己有没有这样一个资源,如果自己有这个资源我就优先加载这个,如果自己没有这个资源我再加载系统主题的图表,这个就是主PACKAGE的概念。

第二个相对更深入一点就是说家单说一点MIUI这边是分几块,一个是原生资源,就是Android给了我们这些图和样式,但是MIUI大家不知道用没用过,如果用过它和原生还是不太一样,我们修改很多东西,这个其实是我们定义到自己的资源里面去了。接下来就是用户他可能要去换这些主题,换这些图片等等这些东西,但是我们又不希望说他那个主题包没做到就去读原生,我们不希望做到这个,我们希望是如果他没有了读这个,所以这个地方引入了分层概念,就是主题包实际上分多层的,每次找的时候是从上到下一直找,如果没有就用原生。不同的层级可以指定接受资源类型,这个不详细展开了。

接下来刚才提到了有一点,怎么去更改,第一个是用户指定,我们刚才说到就是可以做到了,就是用户指定把一个主题包扔过来,你就帮我显示,另外一点就是即时生效,我怎么做到我应用之后它就会生效。回顾一下刚才五种思路,其实这五种思路都有一个共同存在的问题就是资源的刷新问题,实际上我换了这个资源我期待着系统是把这个图片给我换了,但是其实不是这样的,系统做了很多资源访问的优化,他有大量的缓存,还有不同层次的缓存,比如说APP级别还有预加载的资源,这些预加载的资源其实是不同进程共享的物理空间,还有大量的缓存怎么办?我们要清掉它,清掉它怎么办?一般通用的办法很简单就是杀进程,杀进程你起来以后会重读你的资源,但是这些值是适用于这个层次,而预加载这些东西是不变的,所以你再杀进程,这个进程起来以后读的东西还是来的。最后我们没有办法只能重启手机,我们MIUI当时主题风格最开始那版一直沿用的方法,因为没有找到太多太好的办法。当然了后来有一天我们找到了一个宝贝。叫Configuration,这个是什么呢?横屏竖屏我可能有不同的布局,横竖屏一切换就会帮你重新更改数据,或者是键盘显隐,这个就是在Configuration去实现。如果你们不去做这些东西,系统很简单,没什么别的,充气你的Activity,这个Activity是一个站。有了这样一个东西,其实我们当时就觉得黑夜中的一盏明灯,我们由此想到给主题定义一个新的Configuration类型,这个问题就来了,实际上大家写程序,当然我们是很希望以后大家都用MIUISDK开发,但是很可惜不是,大家一般写程序还是基于Android原生的开发,这样不会管我们新定义的Configuration,他也不会去注册,我们自己去维护这个Configuration,我们自己判断你换完了之后,比如说你现在在用短信,用到我这个新的主题包没有短信,我们不需要重启,也不需要管理了,如果你主题包有短信,没办法我重启你的Activity,这样就会重新读资源,当它去读的时候,这个时候由我们自己的代码去接管,这时候就可以读到新的资源了。这个地方就是我们资源刷新的机制。

两点第一点用户自己制定,第二点即时刷新。这个就是我们核心的两个功能点。最后大家可以看到我们可以实现五彩斑斓的主题风格。刚才也说到了这些思路,可能还有很多优化的空间也有很多改进的空间,如果在座各位有谁觉得我们做的这个东西其实不够完善,愿意帮我们去改进,欢迎大家联系我,或者联系我的同事。就讲这些。


图:现场提问

主持人:谢谢董红光。我们问题等一下一起问。我们进入下一个环节之前,我们先请两位讲师和其他嘉宾过来,我们可以和两位讲师有一个比较深入的交流。我最早来到这个房间的时候,有进来的同学有问我说,说我们公司招聘不招聘Android工程师,至少我们现在还没有。但是我先假设小米和友盟都在招。我觉得等一下我们提问的环节也是大家可以掌握自己跟两位工程师交流的机会。我们请另外两位嘉宾也是自己在实际做Android开发的工程师,一个是球球搜冯,还有一位是奇瑞影视的工程师现在在创业做互联网电视的刘金瑞以前也有参加我们的活动。

刘金瑞:今天这个话题我非常感兴趣,因为它能够给我解决一个问题,就是大家在做开发的时候都会遇到一个,我之前做过YP开发的时候我们会很方便更换主题,包括做论坛也好,包括大家做的微博这些东西都很好,我们可以很方便改变我们的主题。但是做系统的主题的时候,对开发人员来说不可能做两套给你,现在如果说我们做到了这个换肤的时候开发人会给你一套两套三套。我们沟通的时候考虑另外的问题,包括做如果说一个界面里面我的界面非常多的时候,会不会有新的影响?我看你讲的时候,MIUI也对这方面有支持,但是对第三方支持还是不够?

董红光:因为MIUI这块目前用户还没有达到更大的规模,但是其实陆陆续续也有一些人去为常用的APP,比如说QQ和微博以前是不支持皮肤的,但是我们是先帮助他们实现换肤的,不过他们现在也支持了。陆陆续续还是会有一些APP,我们之前也有主题大赛和推广等等,而且这个门槛不是很高,可能未来也会有更多的人尝试去做这些东西,可能现在还是过于技术了一些,一些设计师们他们并不是很感冒这些东西,本质上他们还是觉得很复杂,我们未来会尝试把它做的更简化一些。

刚才你说的那个问题,应用这一块交给仙明回答了。我说MIUI这块,其实默认情况下Android会读Framework下面的目录,MIUI是读DATA这个目录,所以从这个上面没有损耗,我们额外还做了很多缓存处理,所以在这个基础上可能反而比原生快一些。

徐仙明:其实红光回答非常好,我想补充两点就是说关于我做皮肤怎么样做优化,就是关于这个资源,因为皮肤更多的时候皮肤资源是在外部,我可能放在SD盘,也可能是放在手机内存里面,正常情况下,我前面PPT里面有一张图讲到说我这些APK是放在一个目录下面,应用比如说我需要加载某一个图片,它会在这个图片里面读出来,如果我放在外部可以从SD卡上读,这个对于图片来说没有什么差别,对于这个APP来说是简单化,这个结构越简单,这个性能就会越高。比如说我们手机上的联系人应用,我手机里面差不多有七百多人,七百多人差不多有七百多张图片,我使用起来还会很快,如果你自己也用到很多图片的时候,不建议你把所有的图片加载到内存当中来。刚才红光提到一个技术叫LRU,就是学过计算机都听说过这个算法,就不是最近使用这些资源就可以释放掉。我听说奇异的客户端以前在Android系统上,因为奇异在播放平台上会用很多技术自己去实现这个,所以通过某一些算法也可以有一些作用。

董红光:刚才大家提到的LRU,这个模式是机遇DACTER的模式。

刘金瑞:Android发布了以后,包括TV、包括IPAD包括大的屏幕和小屏幕的UI,这样在整个资源加载架构上是不是有一些调整?

董红光:其实这个地方并没有做过多的调整,因为Android做的时候不是给一个硬件设计的,因为它涉及到不同的分辨率、不同的屏幕,当时只是为手机,刚才说的就是Drawable有很多目录,有LDPIHDPI等等,当时就是你为不同的分辨率单独放你的图片,这一块升到4.03.0之后这一部分机制没有变化。

徐仙明:我来之前看了一下4.0的变化实际上资源访问的方式跟APK基础上没有变化,4.0主要改变就是在于它提供了很多以前没有的用户交互方式。比如说以前想实现一些LOS上面或者是交互方式,因为3.0属于一个过渡的版本用户不是特别多,4.0把它作为一个标准样式,对于4.0手机硬件结构和按键也发生了非常重大的变化,就是引进了很多UI设计模式,关于UI这方面推荐大家有一个网站可以谷歌一下叫(英文),网上会讲到用户交互的方式怎么设计。如果用IPAD同学,会发现左边是一个导航,右边是内容,这个东西在Android4.0里面得到了很好的支持。

冯:对于开发者来说关于资源加载最核心就是效率,包括速度、内存占用之类的,我想知道不管是在什么开发形式,你们怎么调试资源加载的性能问题?

徐仙明:关于这个LASTVAL是一个很共同的问题了,这个过程就跟我写XML是相似的,或者我会这个面的整个结构弄的很复杂,这样对于我应用的时候就变得很慢。关于LASTVAL会展示它的应用,展示ITEN,这个ITEN类似联系人,我会缓存SP卡里面,如果没有在SP卡就上网上取,我刚开始没有分清楚他们之间有什么太大的差别,就直接做了一个异步的方式,不管从SP卡读,还是网上读,就发现滑动这个过程的时候很卡,而且图片展示会非常缓慢、会有延迟,后来BARG以后,比如说取一个图片,这个过程如果在本地的SP卡里面有就直接同步读,如果本地SP卡没有就考虑异步的方式,这样效率好很多。这样改过之后LASTVAL看起来没有那么卡了。

冯:你怎么发现一改成同步就好很多?

徐仙明:你可以看到你花的时候在表盘上,你会定位某些代码有问题,你可以尝试改一些代码,能够优化一下。

冯:MIUI对这种资源加载,你刚才说了会多更多的缓存?

董红光:刚才提到的问题,我在想我们这边是很悲惨的,因为做Framework,做APP的话Android提供了很多方便的工具都特别好用。其实做Framework我们工程都不能是Android的工程,必须是一个普通的工程,而且不能再一个例子下编译,所以工具这方面没有太多的推荐。APP层有一些。我们这面说到的对于资源访问的优化,其实最多的优化机制实际上主要就是CACH,最简单的就是我拿到一个资源不要用完了就释放,我要把它留住,同时下次访问的时候先从这里面找,这是大家都可以想像得到的,这个存在的问题就是它会占用更大的内容,你一旦使用了CACH就会出现问题,我们尽量少使用,就是用完了就释放掉。还有就是在Framework做一些事情。

冯:还有一个事情就是在听的过程中,在MIUI换肤方案中,允许不允许主题开发者能够自己定义某个控件的行为,某一个文件被查问了以后有一个什么行为,这个方式主题开发者可以定义吗?

董红光:这个暂时是不可以的,技术上是可以做到的,但是实际上我们最终决定不支持这个方式的原因还是一个折中。就是说一般的主题制作者,刚才我也反复提到没有计算机编程的门槛。就是我们MIUI有一个特别突出的一个功能叫百变锁屏,就是锁屏有各种各样的方式,比如说有小虫子飞或者是变形金刚等等的,实际上这些东西通过方式写从某一个点到另外一个点,速度是多少,你中间要不要走一个什么样的曲线等等的,所以我们推出这个功能之后,大部分对这个功能开发的第三方大部分是有一定计算机编程基础,你刚才提到那一点是可以的,但是我们要编程写一些东西,这样可能相应增加一些门槛。回头我们可能会尝试做一些简化的操作,比如说给他提供一些工具做这些事情。

冯:我担心是一个安全问题,比如说他定义了一个(TEXTVIL),按现在的实现我不知道这个开发者定义了一个(TEXTVIL),假设这两个都已经装到系统里了,这个AP可这个恶意的TEXTVIL已经存在了,有可能被ID映射过去,通过这个主题把ID改过去了?

董红光:所以刚才你说的那一点,如果通过这种ID映射那面的TEXTVIL如果那种情况我们肯定要做限制,我们可能要用自己定义的码的方式写,这样所有的代码是公开的,这样可以进行审核。刚才你提到安全性问题,刚才我在演讲过程中也举一些例子,我们现在也存在这些问题,有些人专门恶意搞你这个东西。比如说把是和否互换了,这种方式是没有办法避免的,因为在程序上很难做控制,它是一个寓意的东西。刚才漏讲了一点,这是另外一个很大的东西,就是主题是有一个很大的在线的方式,在线的方式是人工审核的,这个和苹果的很想象,你要开发一个恶意软件是很容易的,但是你走这个苹果的渠道,苹果的程序就会限制的。可能还会有一些更好的方式。

主持人:我留意了一下下面,走了差不多有小一半的人,留下来的人感觉还是很多,可以肯定的是留下的人应该都是工程师。我们接下来就是把这个话筒留给在座的各位,大家看有什么样的问题可以和上面四位嘉宾进行交流可以举手示意。

提问:你好,我刚才是听说采用一种TEXTVIL不会泄露,但是如果我来回切换你们怎么防止呢?

董红光:我们有一个(C),一方面是功能、一方面是性能考虑。

提问:刚才说我开发一个程序之后,怎么样恒定一下我那个程序经过各种各样的程序检测完了说我这个程序没问题了?

徐仙明:我觉得你可以说其实没有非常好的答案,可能说你尽量多的做一些测试,然后你要说想用一些标准的工具,出来的REP会非常好的话,你尽可能做一些测试,有一些网站提供不同机型的测试,在不同的内容大小不一样,会做一些样机测试。

提问:有没有你们常用的工具?

刘金瑞:最常用的就是MAKTEXT。一般来说我们会做一个大概至少是十二小时的压力测试。刚才提到了机星的测试,因为现在做Android的话,不会说每个人有很多Android的机器,顶多是一两个。我记得是在移动开发者论坛上面有这样一个入口,它会处于远程测试,等于你在那边把你的程序传过去,他测试完了会有测试报告给你。

提问:你好我先问一下如何同时安装两个APK?还有文件加载的时候怎么样读取?

董红光:你两个APK打包一个地方,最终这个格式还是一个APK吗?

提问:我现在正在探讨这个问题。

董红光:Android这面安装一个东西首先必须是一个APK格式,如果你把两个APK包打成一个ZIP包是安装不了,最重要去解析你的APK下面Android程序,包括你的ARAC这些文件进行检查,安装过程中会把对应文件拷进对应的目录,所以你把两个APK打包到ZIP上认为是无效的APK

提问:我有没有可能把一个APK另外一个APK安装?

冯:一个APK最核心的部分就是.DEX,假设你说两个APK放到一个里面,这个APK里面有两个.DEX,我可以在执行的时候选择执行哪一个.DEX,这样分别执行哪一个应用,如果这样的话,你用COLSSLODER是可以实现的,但是会很复杂,而且RES管理这块会非常麻烦。我觉得可能不是这个意思。

提问:我的意思是一个安装包里面安装完了以后有一个应用?

徐仙明:你可能把一个APK放在另外一个APK目录下面,你安装第一个APK之后,这个APK启动它会安装另外一个APK

提问:这是一个解决思路,但是我觉得这个解决思路不太好?

徐仙明:另外的可能是你在系统级别改这个Android通过调用有一个应用,你可以修改这个应用的源码,这个是属于系统级别,你做应用是比较难以实现。

董红光:其实就是你刚才说的一点,你是希望把APK安装之后形成两个图标是吗?

提问:不是两个图标,就是一个APK安装之后出现两个应用程序。

董红光:通讯录和拨号你认为是一个程序还是两个程序在Android,在Android中是两个图标但是一个应用程序,安装完了之后会扫描你Android

提问:我不是这个思路。

刘金瑞:我理解你的意思就是类似于捆绑安装,这个地方可以做APK在里面做一个母的APK,只负责安装你这个包里边装的子应用,我这个主APK安装之后这个主APK没有(A),但是这个安装过程必须要用户确认。安装一个用户得确认一次,不能做流氓软件。

提问:我也是做Android的,我补充一个实例,就是油画大师,跟说的用DESK加载一个DESK,就是再一个APK里面可以动态实现茶点式的机制。比如说在油画大师可以加载一些程序下载器,安装一些其他的软件,是不是大概实现你的想法。

提问:你好,我想问一个基础方面的问题,就是我想获得这个文件里面有多少个监听?

董红光:你这个通过XMLPASHER去实现,你可以通过系统提供的XMLPASHER读出来,像RECVER有类似的软件可以改一些。

提问:我现在做就跟这个类似的?

董红光:它的实现机制不是这样的,是我们安装所有的APK之后,在DATA目录下有一个PAKGE开头,里面有所有注册的K,那你就做那个系统软件就可以了。你可以获得到,你也可以拿到LACIT。你如果在Android.MFST这个是可以知道的,但是如果你写在代码里是没有办法实现的。

提问:我想请问一下,就是Android屏幕适配好多人认为这个是一个垢病,就是跟Android不一样,就是屏幕尺寸,一个页面还要做横向版本和纵向版本,请问如何解决那种做一个页面同时匹配多个屏幕尺寸的问题?不知道你们看过IPAD有页面是纵向的话,如果那个IPAD摆成横向那个页面由纵向和横向那个过程中有一个动画的切换效果,不知道那个怎么做?

刘金瑞:我先说一下屏幕问题,一个主流的屏幕Android是提供了ADBI,根据DPI,根据屏幕密度适配做几套这样的图。如果说有特殊分辨率的适配的话,也可以写一个文件夹在RES里边,加你自己的图片资源就可以了。另外还有一个就是在程序代码里的时候,最好是做一些动态的控制,去判断当前的屏幕,去获取到屏幕大小,这样在设计整个你界面的时候,你会发现有些东西,你界面里面如果有目录是可以压缩的,就可以把该固定的地方固定掉,计算大小,把整个的布局做一些调整。对于横竖屏切换来说也是两套LALT就行了。至于横竖屏切换动画没有研究过,只要你做一个动画在嵌进去的时候是可以做得到的。

主持人:因为时间的关系,我们再留最后一个问题。

提问:刚才很多开发者提到开发工具,我想问一下你们平时用的开发工具?

刘金瑞:他提供很多工具,有做布局用的,还有做测试用的,我们常用还有一些优化的,包括内存检测的MAT,这些在开发过程中,开发的时候你可以去网站上看一下他用哪些工具,这些工具都是需要用得到的。

主持人:我们等一下可以再有什么问题可以私下跟几位专家交流。最后我们感谢几位坚持到这么晚,也感谢在座各位坚持到这么晚。今天对我来说是更加挑战的。

最后我们想借这个机会也想我们叫诚征一两位志愿者,我们今天的活动讲的是蛮技术的话题,我们后期整理还是需要帮做评审,如果有哪一位感兴趣第一时间拿到速记稿还有我们的编辑会协助来帮助你们完成这个工作。具体可以跟我们的移动频道编辑张英联系。今天就到这里,感谢大家。


分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics