转自:http://mp.weixin.qq.com/s?__biz=MzI3NzA5MzUxNA==&mid=415711810&idx=1&sn=de8337e627811f8a4c8acce2f426f4ad&scene=0#wechat_redirect
专访罗升阳:老罗的Android之旅
2016-01-16 钱曙光 Linux内核之旅
【编者按】我们常说的智能手机实际上就是手机上加了一个操作系统,那么大部分人都会跟我一样不禁发问,这个操作系统和我们接触更多的电脑上的操作系统一样吗。道家云,看山是山,看山不是山,看山还是山。这三个境界同样适用于前边的问题,你说是不是。
罗升阳(博客),1984年出生,2007年毕业于浙江大学计算机系,取得学士学位,2010年毕业于上海交通大学计算机系,取得硕士学位。毕业后一直从事于互联网软件开发,并且致力于移动平台的研究,特别是对Android平台有深入的理解和研究。在国内知名IT技术社区CSDN上发表了一百多篇高质量的Android系统原创性文章,并且开设博客专栏——《老罗的Android之旅》。积极与网友交流互动,深受大家喜爱,访问量一直居于前茅。同时,著有《Android系统源代码情景分析》一书。
CSDN:请和大家介绍下你和目前所从事的工作。
罗升阳:我现在正在做一款和手游相关的Android应用,玩家可以一边玩游戏一边录制以及直播。在中国,无论是传统的PC互联网,还是现在的移动互联网,游戏都是一个巨大的市场。在手游超越页游追赶端游的今天,手游录制和直播作为连接玩家和玩家、玩家和厂商之间的一个平台,近年来在国内外都得到了追棒。在国外,今年5月初的时候,手游录制及分享社区Kamcord获得了710万美元的A轮融资;到5月中的时候,又传来Google花10亿美元收购游戏直播公司Twitch的消息。在国内,爱拍和ShareSDK也发布了手游录制和分享相关的产品。
手游录制和直播产品吸引我的,除了它的巨大市场之外,还有它的技术含量。坦白说,在Android平台上,至今还没有一款用户体验好的手游录制应用。目前Android市场上的手游录制应用,不是性能问题,就是稳定性或者兼容性问题。包括在iOS平台上已经做得相当不错的Kamcord,在Android平台上也表现平平。究其原因有如下三点:
一是Android平台没有直接提供获取游戏画面和声音的接口。
二是Android平台的差异化导致很难找到一个通用的技术方案使其在大部分手机上都能行之有效。在Root过的手机上,虽然可以使用截屏接口来获取游戏画面,但是直接使用效率是很低的,难以满足帧率要求。另外一个通过读取Frame Buffer获取游戏画面的方法,在到4.0之后,就更行不通了。
再者,由于是实时录制,对视频编码的性能要求是很高的。使用软编码基本上是不可行的,必须要使用硬编码。但是使用编码又要考虑硬件上的适配,否则就很容易产生稳定性和兼容性问题。
为了解决上述的技术难题,需要用到很底层的Android系统知识,例如Android系统的UI渲染机制和硬编码等知识。要利用这些知识,没有深厚的Android功底是很难办得到的。由于我对Android系统有比较深的研究,因此我觉得去做这样的一个产品是一个很有意思的挑战。
当然,目前除了做手游录制和直播应用之外,还在研究做一些基于Android系统的穿戴式设备,毕竟我的兴趣点在于Android系统,而且穿戴式设备也会是未来的方向之一。
CSDN:你是从什么时候接触到计算机的,是怎样走上编程这条道路的?又是在何时开始接触Android平台并进行如此深入研究的呢?
罗升阳:我接触计算机的时间是比较晚的,上大学之前,除了在网吧,基本上就没接触过电脑了。大学选择了计算机专业,才开始真正的接触电脑。而且我很清楚地刻,大一开学大概一个月的时候,学校要进行计算机文化基础上机考试,实际上就是考一下Word和Excel的操作。考试前有大概两周时间让你有空的时候去机房练习。对于一个以前没怎么接触过计算机、打字都还不利索的孩子来说,果不其然就考挂了。后来补考了一次才及格。
由于学的是计算机专业,大一的时候就要开始编程的了。一开始学的就是C语言,不像现在很多人一开始学的是都是C#、Java、PHP这些高级又相当易用的语言了。后来才逐渐学习了C++、Java和C#等这些高级语言。刚开始学C语言还是很痛苦的,龙其学到指针、链表这些知识的时候。记得大一上学期的国庆节,还专门花了几天的时候去啃了链表的实现原理。现在回想起来,一开始就选择学习C语言是对的。因为无论你现在工作用的是什么语言,如果想要把它背后依靠的平台吃透,都不可避免地需要了解它的底层实现,而这些底层实现基本上都是离不开C/C++。或者换句话说,语言只是一个工具,要理解你的软件实现原理,关键都是要理解软件背后的计算机系统,而C是最接近计算机系统的语言。因此,我是非常建议有志于从事软件开发的同学们,无论你现在、以后工作用的是什么语言,都一定要学好C/C++。
接触Android平台是研究生毕业后工作的事了。正式接触是2011年年初的时候,当时写了一个简单的五子棋游戏。不过在2010年下半年的时候,就开始计划要好好研究一下Android系统了。因为了解到Android系统是基于Linux内核实现的,所以2010年下半年的时候,主要就是去补Linux内核的基础知识。其实激发我要去深入研究Android系统而不是单单是Android应用的动机,是当时在公司做的一款软件的应用程序框架,是完全公司的一个团队自行开发的,没有采用在学校时接触的MFC等通用框架。那时候对这套自行开发的应用程序框架很感兴趣,但无奈我们只是业务团队,平时只是使用这套框架,而没有机会去深入研究。
2010年的时候,iOS已经很火了,Android也开始冒出尖尖头了。由于Android背后的靠山的Google,而且它的源码是开放的,因此,就准备去研究一下Android系统的应用程序框架是怎么实现的。这样一来能跟上移动潮流,一来也能满足自己的好奇心。从此就一发不可收拾,正式步入Android系统的世界了。
CSDN:你用两年的时间炼就了深厚的Android内功修养,请问期间的学习之路是怎样的?有什么学习的心得和体会可分享?
罗升阳:那两年基本是把所有的业余时间都花在了学习Android上,包括工作日的下班时间、周末、节假日等。由于是第一次接触这么系统又这么底层的知识,从一开始恶补Linux内核知识,到后来系统地学习Android系统的专用驱动、HAL层和应用程序架构层等知识期间,遇到的困难是可想而知的。以致于在花了两年的时间,完成Android系统研究的第一阶段任务之后,忍不住写了一篇文章《2012年的Android之旅:梦想、学习、坚持、自信、淡定》总结这段学习经历。就像文章所说的,那两年学习Android的心得和体会总结起来就是十个字:梦想、学习、坚持、自信、淡定。由于篇幅关系,这里就不一一展开来说了。不过,我最想分享还是关于坚持这一点。
坚持这两个字真的是说起来容易做起来难。哪怕是一件很简单的事情,要求日复一日地坚持去做,恐怕也是不少人做不到的。举个例子说,锻炼身体。我们不说每天,就说每一个星期拿出一个到一个半小时去锻炼,又有多少个人能坚持做到的呢?这还是花时间去做就能完成的,不会遇到诸如学习、工作、生活上的挑战。所以我们说坚持就是胜利,是很有道理的。只要制定好了目标,就一定要下定决心坚持去完成,无论中间遇到什么样的困难和挑战。当坚持变成一种习惯的时候,离目标的实现就不远了。换句话说,主要你肯坚持,你就会发现:1、你的目标实现了;2、你养成了一种良好的习惯。
经常听到有人说,太难了,看/学/做不下去了。其实,没有什么事情是与生俱来就会的。既然是不会的,学习的过程就肯定要付出代价。2010年下半年之前,我平时学习、工作、和娱乐基本上都是在Windows平台上,第一次学习Linux内核看的是《Linux内核源代码情景分析》 这本书。看过这本书的人都知道,那基本上就是一本天书。当时我对自己说,不紧要,看一遍不懂,我就再看第二遍、第三遍和第四遍。最后执行的过程是,看过第一遍后,心里只是大概有个谱。接着去找一些相关的经典书籍来继续看,例如《Linux内核设计与实现》。看完了《Linux内核设计与实现》,回过头来又接着第二遍看《Linux内核源代码情景分析》。这下就发现原来一些看不懂的地方现在懂了,但是还是有其它地方看不懂。于是,又继续看了《Linux设备驱动程序》和《深入理解Linux内核》等书。每次觉得有必要的时候,都又重新去看一遍《Linux内核源代码情景分析》。经过这样的三四遍折腾之后,最后终于可以很愉快地看懂《Linux内核源代码情景分析》了。
当然,除了有毅力去坚持之外,还要懂得坚持的方法。借用马丁·路德·金的一句话:
If you can’t fly, then run; if you can’t run, then walk; if you can’t walk, then crawl, but whatever you do, you have to keep moving forward。
这句话我觉得重点就是最后三个单词“keep moving forward”。在坚持的过程中,你要让自己觉得自己一直在“keep moving forward”,这样才会有坚持下去的动力。换句话说,就是要让自己在坚持的过程中看得到事情又推进了一步,哪怕是一点点的进步。还是以看书为例子。只要你每天坚持平均看20页,一年就可以看7300页。打个8折,也有5840页,也相当于10本书了。10本书看下来,可以学到的东西是相当多的了。在这个过程中,每天看20页书这件事就是推你向前了一步。有人可能觉得每天看20页书还是太难了。是的,开始的时候可能是有点难。但是,当你坚持一段时间之后,就会发现了解的知识变多之后,看书的速度也跟着加快,到时候不要说一天20页,一天50页都不是问题。
CSDN:你是《Android系统源代码情景分析》(试读地址)一书的作者,这本书是怎样诞生的?这是你的第一本书,写书过程中经历了怎样的困难?随着Andriod的版本更迭,你会出第二版吗?还有其它著书计划吗?
罗升阳:一开始只是想通过博客记录自己学习Android系统的过程,并没有计划写书的。随着博客的人气上升,不断有出版社编辑发出出书的邀请。开始的时候,基本上还是拒绝的。再到后来,也有不少网友建议把博客整理一下成书出版。在出版社和网友的多次建议下,也考虑到有些读者可能更喜欢阅读纸质书,最终就决定把博客的文章整理成书出版了。
第一次写书,怀着的是诚惶诚恐的心情,担心能力有限,误人子弟。书与博客不一样,出书包含有出版社、渠道和销售等成本,因此读者是不可能免费得到的。既然读者要付出钱来购买你的书,那你写书的时候就得负起责任,例如要保证内容的系统性、完整性和正确性,还有文字表达的通顺性,甚至还不能出现错别字。这与在网上写博客有很大的区别。写博客可以比较随意一点,漏掉的内容可以以后再补,错误字也可以马上就修改过来。
基于面这些原因,写书过程经历的困难是可想而知的。决定写书之后,一开始并没有急着去写,而是将计划纲入书里面的内容都先发表到博客上,也就是我在2011年12月前发表的文章。主要是考虑到先将内容发表出来,让读者看到之后可以帮忙发现BUG以及提建议,这样可以帮助提高书的质量。整理博客不是简单的拷贝粘贴,比我想象中要困难多了。回过头来再看自己发表过的文字,百分之七八十都要重新表达。而且有些章节,要系统地描述清楚,单靠博客上的文章是远远不够的。例如,在写Binder那一章时,原以为在博客写的一系列文章已经够完备了,但是发现只是写了一半不到。然后就拼命地一边整理已有的内容,并且一边补新的内容。
在时间上,从开始整理到出版的半年时间里,除了工作基本就是扑在写书上了,而且利用的都是工作之余的时间。没有周末,没有节假日,工作日也是经常熬夜到两三四点。对程序员来说,写文字其实比写代码要累多了,这就是为什么程序员都不喜欢给自己的代码写文档写注释的原因。期间是想过要放弃的,但是已经跟出版社签定了合同,怎么都坚持下去啊。就这样一路走来,从博客文章整理得到初稿,又经过三遍逐行逐行的校对,终于完成了三大篇十六章830页近160万字的著作。说实话,当时要是再让我看第四遍的时候,感觉都要吐了。
Android版本更新的确是比较快,不过目前是没有出第二版的计划了。主要是因为我写的内容都是很基础的东西,例如HAL、Binder IPC、Ashmem、Logger,以及四大组件Activity、Service、Broadcast Receiver和Content Provider的实现原理,它们在后来的版本中仍然是保持性当初的设计思想和运行原理的。我更希望的是,读者看了我的书之后,能够自己去分析Android系统的源码,这样以后Android版本更新得再快也不怕了。
至于新书,以前是有计划的。完成了《Android系统源代码情景分析》一书之后,我又陆续在博客了发表了UI架构、UI渲染、窗口管理、Dalvik虚拟机、编译系统、SEAnroid安全机制等一系列的文章。这些内容加起来也可以有《Android系统源代码情景分析》这本书那么厚了。不过写书是费时费力的事情,而且产出投入比也不高,再加我也不是专职的图书作家,所以现在也不打算出新书了。但是博客是一定会坚持写下去的,希望读者可以持续关注,并且可以在博客上与我交流。
CSDN:初学Android的时候,很多人搞不清Android和Java到底有什么不同,你认为他们之间的区别是什么呢?另外,Android内核跟linux又有什么区别?
罗升阳:实际上,Android是Android,Java是Java。不用Java,用C/C++写的程序,也一样可以在Android上运行。对于这个问题,其实不只是初学者,对于不少有经验的开发者,也会认为做Android应用开发,懂Java就行了。从最近面试的一些人来看,就很明显地感觉到这个问题的普遍性。很多Android应用开发者只懂得使用Android SDK提供的Java接口来开发东西,但是没有进一步去学习一些更深层次的东西。
本质上说,Android是一个Linux系统,因此它是基于Linux内核开发的。但是Android与一般的Linux系统不同的是,它有着自己的一套独特的用户空间运行时,也就是我们通常说的应用程序框架。举个例子来说,以前很多基于Linux的嵌入式开发,就是移植一个Linux内核,然后再用Qt作为应用程序框架,这样一个系统就跑起来了。因此,将Qt应用程序框架替换为Android自己的应用程序框架,就得到了一个现代化的移动操作系统。
在Android应用程序框架中,包含了很多开源工程,例如浏览器用的内核WebKit、管理Wi-Fi网络的wap_supplicant、播放音乐视频的StageFright等,它们都是使用C/C++来写的。而且Android系统专用的用来渲染UI的SurfaceFlinger、用来播放声音的AudioFlinger等,也是用C/C++来写的。更不用提每一个应用程序都要使用到C库bionic、Dalvik虚拟机等了,它们都是用C/C++来写的。这些使用C/C++写的服务,实现了最基本的功能。这些最基本的功能被在Java层的提供的关键服务所使用,例如组件管理服务ActivityManagerService、应用程序安装服务PackageManagerService、网络连接服务ConnectivityService等。最后,Android再封装了一套基于Java语言的SDK给开发者去使用那些实现在Java层的系统服务。
也就是说:Android系统=Linux内核+Android用户空间运行时+ Android SDK,而Android用户空间运行时=C/C++ Runtime Framework + Java Runtime Framework。很多情况下,我们调用Android SDK提供的一个API时,这个API调用会交给Java Runtime Framework处理,而Java Runtime Framework又继续将这个API调用交给C/C++ Runtime Framework处理,最后C/C++ Runtime Framework又有可能接着将这个API调用交给Linux内核来处理。
从上面的调用过程就可以看出,Java只是位于Android最上面的一层编程接口,而没有这一层编程接口Android也是可以正常运行的。我们知道,Android除了提供SDK外,还提供有NDK。也就是说,我们完全可以不使用SDK,而是通过NDK提供的接口绕过Java Runtime Framework,直接将请求交给C/C++Runtime Framework处理。
至于Android系统使用的Linux内核,其实与传统的Linux内核并无多大区别,甚至可以看成是一样的。要说真的区别,就是有两点。一是Android在传统的Linux内核中以模块的形式加入了一些专用的驱动,例如日志驱动Logger、匿名共享内存驱动Ashmem、进程间通信驱动Binder。二是Android系统将在传统的Linux内核实现的硬件驱动程序划分成了两部分,一部分在内核实现,另一部分在用户空间实现,也就是我们常说的硬件抽象层HAL。Android系统之所以要这样划分,是出于商业考虑,而不是技术考虑。因为Linux内核使用的GPL许可协议,驱动全部放在内核实现就意味着需要全部开源代码,而用户空间使用的是Apaache License,可以不开源代码。通过这种方式,就可以保护厂家的商业利益,因为这些代码通常都会包含有硬件的相关参数。
CSDN:Android系统层次结构是怎样的?各个层之间关系是什么?
罗升阳:上面也提到了Android系统的层次,详细一点说,就是:Android = Linux Kernel + C/C++ Runtime Framework + Davik Virtual Machine + Java Runtime Framework + Java SDK。下面我们再以APK的开发、编译、安装和运行来说明这些层次之间的关系。
首先,我们是在PC上使用Android SDK提供的接口来开发APK,用的Java语言。开发完成之后,使用Java编译器将源代码编译成Java字节码,也就是带.class后缀的文件。接下来这些.class再被Android SDK提供的dx工具转化成Dex字节码,最后打包在APK里面的classes.dex文件中。
接着,APK文件在手机上安装时,Java Runtime Framework里面的PacakgeManagerService就会对该APK文件进行解析,并且通过Socket IPC通知C/C++ Runtime Framework里面的installd守护进程对APK里面的classes.dex文件进行优化,得到另外一个classes.odex文件。
APK安装完成之后,就可以运行了。我们以APK从桌面Launcher启动的过程为例说明它的运行过程。当我们从Launcher点击应用图标的时候,Launcher向Java Runtime Framework里面的ActivityManagerService发送一个启动应用的请求。ActivityManagerService又通过Socket IPC向C/C++ Runtime Framework里面的zygote守护进程请求创建一个应用程序进程。这个应用程序进程包含有一个Dalvik虚拟机。应用程序进程创建并且启动起来之后,就会通过它里面的Dalvik虚拟机加载前面提到的classes.odex文件。这样我们的应用程序就运行起来了。
APK的运行过程是依赖于Dalvik虚拟机的。我们可以将它看成是将classes.odex里面的字节码解释成本地机器指令执行。例如,我们在APK里面通过FileInputStream或者FileOutputStream打开一个文件的时候,Dalvik虚拟机就会找到C/C++ Runtime Framework里面的C库bionic提供的系统接口open,并且通过它来打开指定的文件。
我们再以应用程序界面的绘制和渲染过程来详细说明各个层次的关系。首先是应用程序通过SDK提供的UI类向Java Runtime Framework里面的WindowManagerService申请分配一块图形缓冲区。WindowManagerService又是通过Binder IPC向C/C++ Runtime Framework里面的SurfaceFlinger申请分配图形缓冲区的。图形缓冲区实际上不是由SurfaceFlinger分配的,而是由显示系统分配的,可能在显存里面,也有可能在GPU里面。这时候SurfaceFlinger就要通过HAL层次Gralloc模块向Kernel里面的显卡或者GPU驱动申请分配真正的图形缓冲区。HAL层可以看作是运行在C/C++ Runtime Framework中。
应用程序得通过上述方式得到绘制UI所需要的图形缓冲区之后,就开始绘制自己的UI了。假设应用程序使用的是硬件绘制方式,也就是通过C/C++ Runtime Framework里面的OpenGL来绘制。这时候SDK的UI类的与绘制相关的函数调用通过Dalvik虚拟机都转化成了C/C++ Runtime Framework里面的OpenGL操作。
应用程序UI绘制完成之后,结果就保存上述的图形缓冲区中。这时候如果要将该图形缓冲区渲染到手机屏幕上,那么还需要通过Binder IPC将该图形缓冲区发送给C/C++ Runtime Framework里面的SurfaceFlinger。SurfaceFlinger通过使用OpenGL或者HWComposer将所有请求要渲染到手机屏幕上的图形缓冲区合成之后,得到一个主图形缓冲区。最后这个图形缓冲区又会被SurfaceFlinger提交给Kernel的显卡驱动,并且在手机屏幕上进行显示。
上面描述的就是Android系统各个层次的调用关系。总的来说,应用程序运行在Dalvik虚拟机上,并且通过SDK使用Java Runtime Framework里面的服务,而Java Runtime Framework里面的服务又通过C/C++ Runtime Framework里面的服务来实现自己的功能,最后C/C++ Runtime Framework里面的服务又会在需要的时候请求Kernel里面的模块或者驱动来为自己服务。
CSDN:Andriod可以说是开源的代名词,一些开发者为了保护自己的成果进行加密,而另一些开发者为了学习,需要进行APK反编译,可以分享下您对加密和反编译的看法吗?
罗升阳:严格来说,Android系统是开放不是开源。Linux内核才是严格意义上的开源。只要是运行在Linux内核里面的代码,都可以要求作者将代码开源出来。但是运行在Android系统用户空间的代码,作者就不需要将它们开源出来了。这些代码包括厂商对Android官方源码的修改,以及自己增加的代码,还有第三方为之开发的APK代码等。这是由于Linux内核使用的是GPL许可协议,而Android系统的用户空间代码使用的Apache许可协议。
我觉得无论是开发者为了保护自己的成果而对APK进行加密,还是另一些开发者为了学习而反编译别人的APK,都是无可厚非的。当然前提是不要利用这些技术去做坏事,否则的话,就是违反法律的事情了。加密和反编译实际上是一种技术竞争关系。我们都知道,竞争其实是可以推进技术进步的,而技术进步的最终结果对用户是有好处的。
我在这两个讲《Android安全机制》和《APK防反编译技术》的PPT中,有描述过通过DEX和SO加壳、添加非法指令、隐藏敏感代码和伪APK加密技术等办法来保护代码的方法。然而,再厉害的保护技术,只要计算机知识牢固,并且有足够的耐心,再加上一些工具,例如apktool和ida,都是够破解的。当然,在别人破解了你现在的保护技术之后,你可以再发明另外的技术来保护自己的代码。这就是技术竞争,比的是各自的技术水平。
CSDN:深入理解框架层,需要具备哪些知识?对于开发应用具体有什么好处?而开发者在学习这一过程中应注意哪些问题?
罗升阳:从上面对Android系统的描述可以知道,要学入去学习Android系统的框架,需要具备的知识是不少的。
从语言层面来说,需要掌握C、C++、Java,甚至还有汇编。
从系统层面来说,需要有Linux内核基础,包括进程管理、内存管理、文件系统等,还需要掌握Android的HAL、C/C++ Runtime Framework、Java Runtime Framework和Davivk等。
虽然应用开发者平时不用接触系统方面的东西,但是如果能够深入理解Android的框架层,好处是不言而喻的。
首先,可以提高能力和拓宽眼界。因为要看得懂Android系统的代码,要求了解很多知识。要了解这么多的知识,又需要不断地去学习。在学习的过程中,能力和眼界就会自然得到提高和拓宽。
其次,可以正确地使用SDK接口。学习SDK接口,我们一般是通过阅读SDK文档。但是这些SDK文档只是告诉你它们是怎么用的,没有告诉你它们是怎么实现的。如果我们既知道一个SDK接口是怎么用的,又知道它是怎么实现的,那么用起来肯定会得心应用很多。而且在使用出错的时候,也能迅速地通过检查它的实现代码来定位原因。
再者,可以有效地解决BUG。当程序运行出错的时候,系统除了会输出异常信息或者Crash信息之外,通常还有伴随着一些错误日志输出。往往这些系统输出的错误日志包含很丰富的信息,告诉到底是哪些地方出错了。但是这些错误日志是由系统输出的,它们的含义以及输出条件都是由系统定义的。这时候如果要理解到底是什么地方出错了,那就得对系统有一定的理解,甚至需要找到输出这些日志的系统代码来阅读一下。
总之就是技多不压身,学到的东西都是自己的,以后靠这些技术赚到的钱也是自己的。但是前面讲到,要学入理解Android系统,需要具备的知识是很多的。基于这个原因,应用开发者最需要注意的问题就是不要被这个问题吓退。其实是没有人与生俱来就具备这些知识的,而且知识是无究无尽的,活到老就可以学到老。所以一定要坚持学习,一点一滴的积累,哪些不懂就补哪里。开始学慢一点没有关系,等积累到一定程度的时候,就会发现自己的学习能力呈加速度趋势。
CSDN:移动互联网如今发展得如火如荼,Android在其中占居着重要的角色,其发展众说纷纭, 你如何看待Android的未来?
罗升阳:Android的发展问题,无非就是与iOS相比,孰优孰劣的问题。目前在移动互联网上,还找不到第三个可以与Android和iOS抗衡的系统。Android与iOS相比,很多人无非就是觉得:
1. Android UI不够流畅;
2. Android不够安全;
3. Android更耗电;
4. Android兼容性差。
刚开始的时候,Android UI与iOS相比,流畅性的确是差很多。一方面是因为Android手机参差不齐,有些在硬件配置上确实不如iOS。另一方面确实是Android系统自身的问题。但是我们看到自3.0以来,Android就一直在加强UI流畅性进行努力。Android在3.0在应用程序进程这一侧,允许使用硬件绘制UI。在4.1的时候,又通过Project Butter计划,极大地提高了UI的流畅性。到了L版本,又用ART代替了Dalvik,这意味着应用程序运行时执行的是本地机器指令,而不再是虚拟机机指令,性能将得到极大的提升。总之,目前在同等硬件配置下,Android的UI流畅性与iOS相比,差距是越来越小了。我们期待ART代替Dalvik之后,两者可以不相伯仲。
关于安全问题,iOS也有自身的安全问题,例如,每次iOS版本升级后,不也是有人很快就发布了越狱工具吗?同时我们也看到,Android在4.3版本,引进了SEAndroid,用来加强其安全性。SEAndroid是美国国家安全局(NSA)在SELinux的基础上专门为Android系统开发的,用来保证系统即使在被root的情况下,也能最大限度地保护用户手机的安全。另一方面我们也看到,由于Android系统是开放的,有很多第三方的安全公司,例如Bluebox,积极地帮忙发现漏洞,以便可以及时进行修复。
加密算法有一个Kerckhoffs原则:秘密寓于密钥。意思就是说一个密码系统的安全性,应该仅仅依靠“密钥没有泄漏”这个前提。即使整个系统落到了敌人的手里,敌人了整个系统的所有细节,但是如果敌人不知道密钥,你的传输还是安全的。无论是在战争还是和平时期,不能把保密的希望寄于系统/算法的保密性,因为机械的可以拆解,软件的可以看汇编。在这一点上,非公开算法和公开算法的区别就体现出来了:公开算法受全世界的密码学者研究,经受得考验;非公开算法只有除了作者外别人都不知道,可能有很好的攻击但是作者没有发现。我想由于Android系统是开源的,而iOS系统是闭源的,它们的安全性之间的比较可以类比于公开和非公开的加密算法安全性比较。
至于Android的耗电问题,很大程度是由应用程序引起的。由于某些原因,Google官方提供的统一推送服务不能在国内使用,导致了每一个需要网络推送的应用程序都自已在后台启用了一个服务,定时地检查服务器有没有新的通知。即使是手机已经休眠了,也会对其进行唤醒进行检查。这就造成了电量非常大的消耗。iOS有统一的推送服务,并且不允许应用自己设计一套推送服务,因此就可以保证电池的优化使用。为了一定程度上解决这个问题,Android在L版本提供了Job Scheduler服务,用来对齐应用对设备的唤醒,以达到优化电池使用的目的。
至于Android的兼容性,是由于Android系统的开放性造成的。各个厂商都可以将Android源码拿过来进行修改,并且跑在硬件配置各不相同的手机上,因此就造成在一个手机上运行得很好的程序,到了另外一个手机上就可能会出现问题。
归结来讲,Android的耗电问题和兼容性问题,很大程度都是由于Android的开放性导致的。然而,Android的开放性也正是它的优点所在。回想起上个世纪末期,苹果计算机与IBM兼容PC之争,我们就会发现,IBM兼容PC正是靠开放性打败了苹果计算机。当然,今时不同往日,今天依然闭源的iOS和开放的Android,两者除了在手机之外,在车载、穿戴式设备、智能家居方面,也都展开全面的竞争,鹿死谁人还不知。但是,我们现在看到的是,很多创业者,想要做自己的智能设备时,第一时间想到的肯定是使用Android系统。这说明Android系统有群众基础。我们期望众人拾柴火焰高,Android的发展越来越好。
CSDN:对于Android开发的学习者,他们如何在竞争如此激烈的移动互联网环境中提升自己的核心竞争力呢?另外,你能推荐一些书给他们吗?
罗升阳:要在激烈的移动互联网环境中提升自己的核心竞争力,关键还是要提到自己的技术水平,最佳的途经就是持续的不断学习。学习既要有广度,又要有深度。自己感兴趣的知识,一定要深入去研究。其它相关的知识,也要尝试去有一定的了解。
关于学习这个话题,有些人觉得现在用不到的东西就没有必要去学习,否则就太浪费时间了。其实,很多东西等到要用到的时候再去学,就太迟了。要知道,我们通过学习用到的东西,虽然不会直接反应在我们现在工作的内容上,但是也会潜默移化地响应着我们思考方式,把我们往好的方向推动。还有的就是,我们学的所有东西都不会白白浪费的,总有一天都会派上用场的,特别是在当今十年河东十年河西的科技时代。十年前,火的是传统互联网;十年后,轮到移动互联网上场;再过五年或者十年呢?谁都不知道会怎么样,但是只要我们有技术在手,就能积极拥抱变化。毕竟从技术层面讲,无论时代怎么变化,核心的东西都相通的。
要推荐的书,我在《那两年炼就的Android内功修养》这篇文章中有提到,这里再列一下出来:
语言类:
- 《深度探索C++对象模型》,对应的英文版是《Inside C+++ Object Model》
- 程序编译、链接、加载类:
- 《链接器和加载器》,对应的英文版是《Linker and Loader》
- 《程序员的自我修养:链接、装载和库》
操作系统类:
- 《Linux内核设计与实现》,对应的英文版是《Linux Kernel Development》
- 《深入理解Linux内核》,对应的英文版是《Understanding the Linux Kernel》
- 《深入Linux内核架构》,对应的英文版是《Professional Linux Kernel Architecture》
- 《Linux内核源代码情景分析》
网络类:
- 《Linux网络体系结构:Linux内核中网络协议的设计与实现》,对应的英文版是《The Linux Networking Architecture: Design and Implementation of Network Protocols in the Linux Kernel》
- 《深入理解LINUX网络技术内幕》,对应的英文版是《 Understanding Linux Network Internals》
设备驱动类:
- 《Linux设备驱动程序》,对应的英文版是《Linux Device Drivers》
- 《精通Linux设备驱动程序开发》,对应的英文版是《Essential Linux Device Drivers》
虚拟机类:
- 《Java SE 7虚拟机规范》
- 《深入Java虚拟机》,对应的英文版是《Inside the Java Virtual Machine》
- 《Oracle JRockit: The Definitive Guide》
嵌入式类:
- 《嵌入式Linux开发》,对应的英文版是《Embedded Linux Primer》
- 《构建嵌入式Linux系统》,对应的英文版是《Building Embedded Linux Systems》
ARM体系架构类:
- 《ARM嵌入式系统开发:软件设计与优化》,对应的英文版是《ARM System Developer's Guide: Designing and Optimizing System Software》
综合类:
- 《深入理解计算机系统》,对应的英文版是《Computer Systems: A Programmer's Perspective》
同时,我自己也是处于不断的学习中,平时也会看其它比较多的书,大家有兴趣的话,可以关注我的新浪微博(@罗升阳),上面有不定时的推荐。
CSDN:你在CSDN的社区中具有着极高的人气,博客专栏“老罗的Android之旅”受到大家的追捧,当初你为何选择写博客?写博客给你带来了什么好处?
罗升阳:当初选择写博客,是写给自己看的,当笔记用。否则如果什么都不写的话,研究过的东西很快就忘记了。直到现在,在需要的时候,我都会去翻自己的博客。随着博客读者越来越多,博客就不再是给自己当笔记用了,还是一个用来学习交流分享知识,以及结识志同道合的朋友的场所。
不过,我觉得最重要的是,通过发表博客文章,可以让对我Android的研究更加严谨、更加详细、更加系统。因为每天这么多读者浏览你的文章,你就必须要保证文章的质量,否则的话就会误人子弟,也会毁了自己的名声。为了写出有质量的文章,就必须要严谨、详细和系统地去研究Android系统的代码。因此,写博客和研究Android是一个相互促进的过程。
CSDN:你是什么时候接触CSDN的?它对你学习和工作都带来哪些影响?同时,对CSDN有什么建议?
罗升阳:在写博客之前,其实是比较少接触CSDN。2011年6月决定要通过博客来记录自己研究Android的历程时,也尝试过找其它的博客网站来写文章。最后发现CSDN文章贴的代码显示格式用户体验挺好的。于是就决定使用CSDN博客了。