到了2018年,作为Android开发者,倘若没看过一些Android源码,都不好意思说自己是Android工程师了吧?
之前一直是在GrepCode(http://grepcode.com/)上看的。这是一个相当老牌的Android源码在线查看网站。虽然上面缺少了近几个新版本的Android 源码,但胜在源码种类多,除了Android,还有其他软件的源码可以阅读;易上手,代码之间能相互索引,查看方法引用、继承关系、类的结构和跳转这些功能都很好用,还能方便在切换同一个文件的不同版本的源码。令人悲伤的是,它已经挂了好长一段时间了。: - (
另一个源码阅读网站AndroidXRef(http://androidxref.com/)也很老牌,但用的不多。这个网站专注于Android源码,从远古版本到最新版本都能在上面找到。功能够用,可以查看方法应用、类的结构和跳转这些。继承关系、版本间跳转这些就没有。目前还活着,只是受限于国内的网络环境,访问起来有点慢。
选择在线的方式阅读源码,主要是嫌麻烦。一来是不经常看,主要是查疑难bug的时候看;二来是不方便,Android 发展了十年,源码相当庞大,有十几个G之多,前几年尝试过clone,结果拉了几天才拉完;三来是编译环境不好配,官方的源码编译说明看着不多,实际操作没那么简单,之前的尝试都失败了;最后则是这两个在线查看代码的网站都能满足看代码的需求,也没编译的需求,也就一直这么过来了。
然而看源码最舒服的方式莫过于直接用IDE(如Android Studio),功能多,用起来顺手,而且还可以编辑。等等,编辑?还想改代码不成?并不是这样滴。架不住年纪大了,一些看过的源码慢慢的就遗忘了。俗话说好记性不如烂笔头,编辑的需求,也就是给源码加注释加批注罢了。如果仅仅是看代码的话,Android Studio通过SDK Manager下载Source Code就可以了。
需求变了,在线看源码的法子,就行不通了。真是应了那句话:天道好轮回,苍天绕过谁。不对,应该是躲得了初一躲不过十五,之前那些避开的麻烦,还是需要去面对的。
Clone Android Repository的全部源码,这辈子肯定是不可能的。近期想看的是Support Library的源码,所以我在程序员的网站GitHub上找到了AOSP-Mirror这个Organization,clone了一份support library (https://github.com/aosp-mirror/platform_frameworks_support)的源码。
拉代码的过程挺顺利,用Android Studio打开,完了,Gradle没法build过去。Build不通过就没生成索引,没索引就Android Studio就从IDE沦为普通编辑器,那些强大的功能全都用不上,还不如用understand。
好在,在某个风和日丽月黑风高的晚上,借着天时地利人和,通过命令行运行Gradle得到的错误输出,一点点地改各类.gradle
文件,最终把Gradle Sync
这一步搞定了。后面又精简了一下改动范围,然后把这些改动,push到了自己fork的 platform_frameworks_support
项目的buildable
分支里。有需要的可以到这里(https://github.com/SR1s/platform_frameworks_support/tree/buildable)自取。
改动的地方不多,涉及5个文件。改动的内容总结起来就是:
- 修改buildscript使用的maven库,引入了jcenter和google这两个公共的maven库
- 修改 dependencies 使用的maven库,引入了几个公共的maven库,去掉了源码里指向android源码工程里prebuilts文件夹的那几个maven库
- 去掉settings.gradle里配置的几个module,一类是外部module,即代码不在
platform_frameworks_support
里的module;另一类是依赖的这些外部module的module,这几个的代码现在不关心,所以先挪去它们在settings里的配置(源码还在) - 修改gradle wrapper使用的gradle的下载地址,源码里指向的是本地,也就是android源码工程里防止prebuilts文件夹下的gradle的地址,这里改成网上公共的gradle版本的地址。
涉及的5个文件如下:
- buildSrc/build.gradle
- buildSrc/init.gradle
- buildSrc/repos.gradle
- gradle/wrapper/gradle-wrapper.properties
- settings.gradle
build.gradle
给buildscript添加了jcenter和google这两个maven库。源码里指向的是源码中的prebuilts目录,这个目录不在这个repo里,我去翻了翻,prebuilts目录里东西非常多,也就是很大,拉下来不现实,另外自己一个个单独下也不现实,还是直接用jcenter这类公共maven库方便。添加google的maven库是因为google现在把自家库往里放,没有发布在jcenter里了。(后面我试了下,不加google的这个maven库也是可以的)buildSrc/init.gradle
这里改动一个是注释掉了enableDoclavaAndJDiff
这个方法内的实现代码,这个是给project添加jdiff和doclava这两个依赖和配置,一个是diff工具,一个是文档工具,这两个依赖都是android源码里的其他工具的project,只是为了看代码,用不着这两个,注释掉也不影响。
另一个就是去掉project.ext.androidJar
和props.write
这两句,前者把androidJar指向了prebuilts目录内的最新的android.jar,后者往local.properties
文件里写入配置。前者去不去掉其实无所谓,不影响,后面那个因为会往local.properties
写入android.dir
的路径配置,从而覆盖掉ide内设置的android.dir
,那个配置指向的是当前工程的父级目录,正常情况下,我们的sdk肯定不放哪里,因而build就找不到相关的工具出错了,所以要把这个写入注释掉,用Android Studio设置里的那个就行了。buildSrc/repos.gradle
这个文件定义了一堆本机上的依赖库的地址,实际上就是android源码里的prebuilts目录内的一些具体的目录。地址都放在ext.repoNames
这里,然后通过下面addMavenRepositories
方法,给RepositoryHandler
加上这些maven库。牢记我们没有prebuilts
目录,这些maven库指向的地址自然也是无效的。因此这里再加了一句ext.repoNames = []
,把列表重置成空列表,这样后面加这些maven库的代码就无效了。
另一个是要让Repository能找到依赖。原来官方代码是让gradle去prebuilts
下找,现在我们把这个配置去掉了,依赖也就找不到了(不去掉也找不到啊哈哈),那么就要跟之前对buildscript做的事情一样,加上公共库。刚好下面有个if语句,在符合条件下,会给Repository加外部maven库,所以就注释掉if判断,让内部的代码强制执行,也就自然加上了外部maven库,依赖就能被找到了。gradle/wrapper/gradle-wrapper.properties
这个很简单,把wrapper依赖的gradle的下载的地址改成网络上的,之前的配置指向的是android repo的tools目录,再次的,我们没有这个。所以,改成从网络上可下载的地址:https://services.gradle.org/distributions/gradle-4.4-bin.zipsettings.gradle
这里做的事情简单概括起来就是:去掉了项目里的
support-emoji
、support-emoji-bundled
、support-emoji-appcompat
、support-emoji-demos
这几个module的定义,原因是它们或直接或间接的依赖了另一个不属于这个repo的noto-emoji-compat
module,这块代码目前没想着去看,先不管。去掉不属于这个repo的module的定义,分别是
doclava
、jdiff
、noto-emoji-compat
这三个,他们的源码都在Android大项目的源码的external
文件夹里,是在想引入这几个的,可以去down下来,然后配置。
相关的代码变更都在这个commit(https://github.com/SR1s/platform_frameworks_support/commit/a23529ad2ca019624af9213daf2836e78ce579a2)里,大家都是工程师,一看就懂。
终于可以好好看代码了,欧耶。