阅读 5216
(Android源码)掌握Android阅读源码的两种简单方式

(Android源码)掌握Android阅读源码的两种简单方式


学习背景

最近在看《Android开发艺术探索》书籍,想突破一下自己知识的瓶颈,发现书中有许多知识都结合的源码进行讲解的。源码是我一直很畏惧的区域,很多时候遇到问题在网上搜索解决方式时,遇到长篇大论说源码的,我就会看不下去。如果想让我的技术得到进阶,那就必须得慢慢地区尝试阅读它,最终希望可以通过阅读源码发现或解决实际中遇到的问题。

阅读源码的方式

这里只提供网上比较常见的简单的阅读方式,网上也有许多关于下载与编译源码相关文章,由于我只需要满足阅读的要求,就不做过多的研究。

拓展内容: 以下几个是下载源码过程比较完整的文章:

Android官方源码下载的地址及教程

Android版本的平台代号、标记和Build号

下载AOSP android源码(最小最快下载方式,跳过编译直接导入Android Studio) Ubuntu 16.04

在线阅读源码 - AndroidXRef

这种方式操作简单,效率高。

  1. 进入网站: AndroidXRef

支持多数的源码版本
可以看到支持的android source 到android 9.0 虽然不是最新的android10,但几乎能满足我们绝大多数的阅读需求。

  1. 点击查看 2018-08-11 - New Index: Pie - 9.0.0_r3 的源码分支

源码分支
实际是一个快速搜索源代码的引擎。

以下部分参考: AndroidXRef的帮助文档 在线看Android系统源码,那些相见恨晚的几种方案

界面右侧: 提供在特定目录下搜索,例如在分析 Framework源码时,可以选择 frameworks 目录,这样可以减少搜索范围,缩短搜索时间,能够更加精确地定位到需要的源代码。

界面左侧: 提供了一些搜索的条件,其意义如下(在指定的 Project(s)下):

字段 作用
Full Search 全文搜索,搜索索引中的所有文本标记(单词,字符串,标识符,数字)。搜索符号:覆盖符号的定义及使用,包括注释出现该符号 。
Definition 仅查找符号定义。例如搜索xx函数在哪些类中有定义。
Symbol 仅查找符号。包括该符号的定义及使用位置。
File Path 源文件的路径。搜索源码文件名中包含给定字符串的文件。(类级别)支持输入类名等。方法名通过前三种方式搜索!
History 历史记录日志注释。

上述的符号:可以是代表你要搜索的内容,如变量、方法、类等。以上仅是个人理解。

  1. 使用流程:
graph LR
    id1(界面左边在特定字段输入关键字)-->id2(界面右边选择特定目录,不确定select all即可)
    id2-->id3(点击search)
复制代码

以搜索ActivityThread#handleLaunchActivity的方法为例:在查看handleLaunchActivity()这个方法在哪里定义的

  • Definition 中输入handleLaunchActivity
    Definition查找handleLaunchActivity定义的结果
    可以看到在 ClientTransactionHandlerActivityThread 类中都有定义,前面有写着具体的行号【xxxx】,点击进去可以看出 ActivityThread 其实是 ClientTransactionHandle 的一个子类,handleLaunchActivity 方法其实是 ClientTransactionHandler 的抽象方法, ActivityThread 进行实现而已,点击相应的文件即可跳转,貌似还不支持点击直接跳到出现的行位置。

  • 试着将在 Symbol 中输入:handleLaunchActivity 会得到怎样的结果?
    Symbol的搜索结果
    我们可以发现,相比上面的 Definition 还多了两个类 TransactionExecutorLaunchActivityItem ,因为在这两个类中调用了 handleLaunchActivity 这个方法,这就是 SymbolDefinition 的一个区别,它不仅可以找到那个方法,还能找到在哪里使用。

  • Full Search 搜索包括以上两种搜索的结果,并且还可以找到在注释中出现的位置。不做解析

  • File Path 下搜索 handleLaunchActivity 看看
    File Path搜索结果
    显示搜索不到,File Path 一般是以类名进行搜索的。

搜索 ActivityThread 就可以了。

类名搜索结果


  • History 只是个人含糊的理解 搜索 ActivityThread 出现类型git提交分支一样的提交历史,貌似是查看它所出现的历史。

以上只是单个搜索,还支持多条件搜索,需要更高级的搜索语法。 请参考:Opengrok搜索帮助


在Android Studio中阅读源码

其实最开始,我了解的阅读源码的方式是Android提供的SDK里面的源码包。以android29为例

资源准备

保证你的SDK有以下两个文件目录:

  1. sdk路径/platforms/android-xxx :该文件夹下存放不同版本的Android系统。
  2. sdk路径/sources/android-xxx:该文件夹下存放了Android的源代码。
    platform与sources文件夹

资源下载

如果没有该如何下载? platforms的下载:

sources下载:

  • Android Studio 中下载 Tools——SDK Manager——Android SDK /SDK Platforms——底部选中show package detail——可以看到是否选择了 sources for Android xxx,如果没有选择并apply即可下载。
  • 直接下载 sources/android-28 | sources/android-29
  • 搜索引擎搜索

说明:xxx表示android的版本。(对应项目build.gradle中 compileSdkVersion: 29) compileSdkVersion是编译所依赖的Android SDK的版本。更多SDK目录含义介绍参考:Android SDK目录含义介绍


资源准备好了,接下来打开项目,以Activity为例,选中 mac 快捷键 command+B(或者command+鼠标左键),

Activity源码

遇到的问题及解决方式

  • 遇到的问题:

是不是这样就完成了呢?有没有发现很多类都爆红,点击进去没有反应,导致看到关键的时候,无法看下去了,为什么呢?

搜索引擎一下原因: 总结:是Google公司由于安全和稳定等因素考虑,部分源码是不对外开放的。

需要注意的是 @hide 参考:听说 Android 9.0 要禁用 @Hide Api 的调用,你怎么看?


  • @hide 方法

众所周知,Android 系统在迭代的过程中,越来越重视安全这个因素。而有一些方法可能会涉及到系统安全、用户隐私或者其他一些原>因,总之有一些因素考量,在发布出来的时候,被 Google 标记为 @hide,表示并不希望开发者去使用它们。 而这些标记为 @hide 的方法,我们也是无法直接调用的,只能使用反射的方式去调用它们,这本身就是不安全的操作。 不过呢,我们有时候确实为了实现一些功能,需要使用到这些被标记为 @hide 的方法。


  • 解决方式: 启发文章:AndroidStudio下阅读源码的正确姿势 总结一下这篇文章的结论,将 SDK location/platforms/android-xxx/android.jar 和 framework.jar结合在一起生成新的android.jar。这个jar可以在开发中使用Android的内部/隐藏API。

  1. SDK location/platforms/android-xxx
  2. 将下载对应api版本修改后的android.jar,粘贴并替换到该目录中,例如android-29/android.jar。
  3. 最后,Android Studio中ReBuild你的项目。

  • 遇到的问题:android-hidden-api中下载指定的api的android.jar替换后,gradle编译不通过,提示如下:
> Task :app:lint FAILED
Calling mockable JAR artifact transform to create file: /home/user/.gradle/caches/transforms-1/files-1.1/android.jar/7470a0577854d0dc407ece72235e8952/android.jar with input /home/rgordeev/Android/Sdk/platforms/android-28/android.jar

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:lint'.
> Could not resolve all files for configuration ':app:androidApis'.
   > Failed to transform file 'android.jar' to match attributes {artifactType=android-mockable-jar, returnDefaultValues=false} using transform MockableJarTransform
      > java.lang.IllegalArgumentException (no error message)
复制代码



现在再到Activity源码看:

替换android.jar后的activity源码
几乎很少爆红的了,极少的内部资源(com.android.internal.R.)不能看,如果有强迫症,那就配合在线阅读源码的方式就OK啦!现在我们了开始快乐的学习源码啦!O(∩_∩)O哈哈~


2020/06/01更新 遇到问题:调试进入源码行号不对

通过AndroidStudio调试阅读源码,发现调试进入行号与自己的sdk/sources的不一致,还会出现行号跑到注释里去的问题。

解决方式

  • Debugger/Frames里可以看到调用到哪些方法,即可以知道这一步进入的是哪个方法,通过Command+F快捷键在对应的源码类中搜索方法名即可定位到正确的位置。这样虽然可以找到正确的方法的行号,但是并没有实际解决问题。
  • 网上搜索了一下,总结几点原因:
  1. 使用真机调试,因为很大部分国产手机可能对源码进行了修改。
  2. 使用的compileSdkVersion版本(编译所依赖的Android SDK的版本,对应 sdk/platforms/android-xxx)与模拟器的运行的API版本不一致。
  3. 使用非官方模拟器,比如我用了genymotion模拟器,同样是api29,compileSdkVersion版本也是29,但是仍会出现行号不一致问题,切换回官方的模拟器,行号就一致了。
文章分类
Android
文章标签