学习背景

最近在看《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. 使用流程:
界面左边在特定字段输入关键字
界面右边选择特定目录,不确定select all即可
点击search

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

  • Definition 中输入:handleLaunchActivity

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

  • 试着将在 Symbol 中输入:handleLaunchActivity 会得到怎样的结果?

    我们可以发现,相比上面的 Definition 还多了两个类 TransactionExecutorLaunchActivityItem ,因为在这两个类中调用了 handleLaunchActivity 这个方法,这就是 SymbolDefinition 的一个区别,它不仅可以找到那个方法,还能找到在哪里使用。

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

  • File Path 下搜索 handleLaunchActivity 看看

    显示搜索不到,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的源代码。

资源下载

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

  • Android Studio 中下载 Tools——SDK Manager——Android SDK /SDK Platforms——选择你要下载的版本即可
  • 直接下载 platforms/android-28 | platforms/android-29

sources下载:

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

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


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

遇到的问题及解决方式

  • 遇到的问题:

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

搜索引擎一下原因:
总结:是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。

  • 具体流程: 参考:android-hidden-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.jarFAILURE: 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)

  • 导致的原因: 在issue#46 Android Studio 3.2.0 sync error: Failed to transform android.jar有解释:
    Android Studio 版本 3.1.4 、Gradle 4.6 使用所提供的28以下的android.jar 貌似没问题,如果Android版本过高,则需要利用其它的方式来生成android.jar。自定义android.jar 具体请看android-jar-with-hidden-api利用aosp(Android Open-Source Project。“Android 开放源代码项目”。)源码来生成可访问AOSP隐藏API的android.jar

  • 解决方式:
    直接使用别人通过源码生成的android.jar
    直接下载 android-28/android.jar | android-29/android.jar 替换 rebuild项目即可。(上面的issue里有资源下载的地址,下载速度可能比较慢

现在再到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阅读源码的两种简单方式相关推荐

  1. Ajax提交Form表单的两种简单方式

    在现在的项目开发中,ajax的应用是必不可免的,最为基本的就是利用ajax的异步处理方式来向后台提交数据.关于ajax提交表单我利用到了两种简单的方式. 方法一## 先获取表单里面的数据,再通过aja ...

  2. halcon颜色识别的两种简单方式

    颜色识别的两种简单方式: 1.单通道方式: 原理:通过不同颜色在灰度图中的阈值范围不同来区分颜色(理论上这种方式不推荐,但在一定情况下适用) 材料: halcon代码: dev_close_windo ...

  3. IDEA MAVEN项目打包成jar包的两种简单方式

    IDEA MAVEN项目打包成jar包的两种简单方式 准备了两个打包方法 1.IEDA自带打包方法 2.用Maven插件maven-shade-plugin打包 IDEA自带打包 适用于任何打包,稍微 ...

  4. 阅读源码的三种境界 (转自 码农翻身 微信公众号)

    刘欣 码农翻身 "没有经验的技术差底子薄的初级程序员,如何阅读项目源码? " "有人阅读过 mybatis 的源码吗 ?就看一个初始化过程就看的已经头晕眼花了,小伙伴们支 ...

  5. 阅读源码的三种境界 (转 码农翻身 微信公众号)

    "没有经验的技术差底子薄的初级程序员,如何阅读项目源码? " "有人阅读过 mybatis 的源码吗 ?就看一个初始化过程就看的已经头晕眼花了,小伙伴们支支招吧!&quo ...

  6. Android阅读源码从工具开始

    常言说:工欲善其事,必先利其器,所以要很好的阅读Android的源码,就先准备好工具. 第一款工具:VPN 由于天朝的原因,Google的很多东西我们都无法阅读,所以第一步就是突破.之前用的是红杏这个 ...

  7. GitLab下载源码的两种方式(https/ssh-key)

    如今很多公司使用git来作为代码版本控制工具,现所在公司是自己搭建私人的GitLab来管理代码的,GitLab中使用git clone下载源码时,支持https和git(即ssh)两种方式下载源码. ...

  8. python恶搞程序-愚人节恶搞程序源码【两种语言】

    Python: print("--------------------------") print("[愚人节专用恶搞程序]") print("[By ...

  9. STM32项目设计:基于STM32F1的智能门锁PCB、源码(4种解锁方式)

    文章目录 前言 一.项目简介 (一)功能概述 (二)项目所用到的主要技术 (三)本次项目的特点 二.材料选择 三.原理图设计 四.PCB设计 五.源码设计 六.安卓APP设计 七.成品展示 项目视频 ...

  10. Android面试,BroadCastReceiver的两种注册方式的异同

    在Android手机应用程序中开发中,需要用到BroadcastReceiver来监听广播的消息.在自定义好BroadcastReceiver ,需要对其进行注册,注册有两种方法: 一种是在代码当中注 ...

最新文章

  1. C#设计模式(8)-Builder Pattern
  2. gulp打包js/css时合并成一个文件时的顺序解决
  3. 集群文件系统GlusterFS安装配置
  4. Angular中父组件通过ViewChild调用子组件的方法
  5. javascript 对象的设计模式
  6. C++总结笔记(十)——堆区内存开辟数组和二级指针
  7. 镭波笔记本安装linux,镭波笔记本windows7旗舰版系统下载与安装教程
  8. 如何使用CppUnit进行单元测试
  9. Altium Designer20原理图绘制
  10. angular自带的一些api_Angular API
  11. 荣耀赵明:电视开关机广告不符合商业逻辑 用户需享受收益分成
  12. 利用VB函数Dir()实现递归搜索目录
  13. 一个人独立完成一个网站上线的前前后后
  14. Python数据结构之字节,字节数组
  15. JMH(java代码的微基准测试)入门和汇总
  16. Linux系统mysql半同步复制
  17. 各类学生机万能卸载攻略
  18. 如何运行app和exe程序
  19. 2. 匈牙利命名法
  20. BeanUtils之populate的用法

热门文章

  1. (9)Redis-Cluster集群理论及实践【下】
  2. 四十一 Python分布式爬虫打造搜索引擎Scrapy精讲—elasticsearch(搜索引擎)基本的索引和文档CRUD操作、增、删、改、查...
  3. Spring Boot实战笔记(四)-- Spring常用配置(事件Application Event)
  4. 集合(ArrayList、Hashtable、泛型集合)
  5. [f]class获取元素函数
  6. 防范项目中人员频繁变动的风险
  7. 基于HMM的语音识别技术原理
  8. golang gin mysql_Golang 的Gin框架入门教学
  9. 用vscode做markdown编辑器(借助Markdown All in One)
  10. DPDK - RSS