前言

最初开发Android应用程序的时候,肯定是在打log调试,然后慢慢地觉得打log效率太低下了,不能快速定位问题,于是走上了断点调试之路。Gradle插件也一样,从会写插件那一刻起到现在,一直用的是打log调试功能,但是同样的这种方式效率也太低下了,这之前,我也尝试过寻找断点调试的方式,但是一直没有成功,昨天偶然之间调通了,于是记录一发。

之前失败的方式

之前测试断点调试的功能的时候,一直在build.gradle中直接测代码,测试的代码也是在project.afterEvaluate之后,然后遍历android..applicationVariants,获取各个信息,就像这样子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.3'
}
}
dependencies {
compile gradleApi()
compile localGroovy()
}
import com.android.build.gradle.api.TestVariant
import com.android.build.gradle.api.UnitTestVariant
import com.android.build.gradle.internal.variant.ApplicationVariantData
import com.android.build.gradle.internal.api.ApplicationVariantImpl
project.afterEvaluate {
if (project.plugins.hasPlugin("com.android.application")) {
def android = project.extensions.getByName("android")
android.applicationVariants.all {ApplicationVariantImpl variant ->
project.logger.error "DebuggerPlugin:${variant}"
ApplicationVariantData apkVariantData = variant.getApkVariantData()
ApplicationVariantData variantData = variant.getVariantData()
TestVariant testVariant = variant.getTestVariant()
UnitTestVariant unitTestVariant = variant.getUnitTestVariant()
}
}
}

于是这个断点我打了一年硬是没打住,恩,没错,这个东西我断断续续实验了一年也没有成功过,也有点无语,原因也不知道。昨日发现,必须得在外面包一层plugin才能打住断点,就像这样子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.3'
}
}
dependencies {
compile gradleApi()
compile localGroovy()
}
apply plugin: DebuggerPlugin
import com.android.build.gradle.api.TestVariant
import com.android.build.gradle.api.UnitTestVariant
import com.android.build.gradle.internal.variant.ApplicationVariantData
import com.android.build.gradle.internal.api.ApplicationVariantImpl
class DebuggerPlugin implements Plugin<Project> {
void apply(Project project) {
project.afterEvaluate {
if (project.plugins.hasPlugin("com.android.application")) {
def android = project.extensions.getByName("android")
android.applicationVariants.all {ApplicationVariantImpl variant ->
project.logger.error "DebuggerPlugin:${variant}"
ApplicationVariantData apkVariantData = variant.getApkVariantData()
ApplicationVariantData variantData = variant.getVariantData()
TestVariant testVariant = variant.getTestVariant()
UnitTestVariant unitTestVariant = variant.getUnitTestVariant()
}
}
}
}
}

具体原因也找不到,理论上来讲,两者没有什么大的区别,除非不包plugin的代码编译后代码位置发生了变化,导致打不到断点。

其实这事也怪自己,如果一开始直接用插件项目来测,将其发布到本地maven,然后执行去打断点,估计老早就成功了,硬是在build.gradle中写零碎的代码来测试,往事不提也罢。

一个坑

以上代码执行过程会先出现一个错,如下:

1
Error:The closure 'DebuggerPlugin$_apply_closure1$_closure2@20825b3e' is not valid as an action for argument 'com.android.build.gradle.internal.api.ApplicationVariantImpl_Decorated@1103b69d'. It should accept no parameters, or one compatible with type 'com.android.build.gradle.internal.api.ApplicationVariantImpl_Decorated'. It accepts (com.android.build.gradle.internal.api.ApplicationVariantImpl).

这个错出现的时候,只需要将ApplicationVariantImpl variant改成def variant即可,然后继续运行,会出现另一个问题。

即出现了一个cannot cast object with class A to A的问题,如下

1
Error:Cannot cast object 'ApplicationVariantData{debug}' with class 'com.android.build.gradle.internal.variant.ApplicationVariantData' to class 'com.android.build.gradle.internal.variant.ApplicationVariantData'

可以看到虽然两个对象obj1和obj2的类的名字相同,但是这两个类是由不同的类加载器实例来加载的,因此不被虚拟机认为是相同的,所以抛出了ClassCastException异常。

那么怎么解决呢,将项目中所有buildscript中的dependencies下引用的android gradle plugin 版本都改成同一个,即

1
2
3
4
5
6
7
8
buildscript {
repositories {
jcenter()
}
dependencies {
classpath "com.android.tools.build:gradle:${global_gradle_plugin_version}"
}
}

之后将~/.gradle/daemon/目录下内容全部删除,然后看看是否解决了,如果没有解决,则继续删除~/.gradle/daemon/,然后重启电脑。TM的如果还没好,那么请确定项目中所有引用的插件中的compile的android gradle plugin版本是否都一致,如果不一致,请保持一致,不然也有问题。

这问题就算完事了,大概可能和Gradle的守护进程、插件引用的android gradle plugin版本不一致有那么一点关系。

断点调试方式1

说完了以上坑,正式进入断点调试的环节,方式一很简单,直接利用gradle的参数让其等待我们的调试进程attach上去。比如我要执行gradle clean这个task,则加上两个额外参数即可

  • 一个是开启debug
  • 一个是不使用守护进程

    具体例子如下:

    1
    gradle :app:clean -Dorg.gradle.debug=true --no-daemon

    之后这个进程就会一直等待,直到我们attach我们的调试进程。如下图所示:

然后参考这篇文章Intellij-IDEA远程调试,利用Android Studio或者Intellij IDEA的remote debug进行调试,端口号填5005.

如图

然后运行remote

之后就会attach上去我们的进程

然后看看效果

从此可以愉快的断点调试了。

断点调试方式2

和方式一差不多,只不过不是用gradle的参数来开启debug,而是用环境变量

1
export GRADLE_OPTS="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005"

之后就跟正常执行任务一样

1
gradle clean

剩下的操作和方式1一样。

http://fucknmb.com/2017/07/05/%E5%8F%88%E6%8E%8C%E6%8F%A1%E4%BA%86%E4%B8%80%E9%A1%B9%E6%96%B0%E6%8A%80%E8%83%BD-%E6%96%AD%E7%82%B9%E8%B0%83%E8%AF%95Gradle%E6%8F%92%E4%BB%B6/

又掌握了一项新技能 - 断点调试 Gradle 插件相关推荐

  1. 学习一项新技能的公式

    **学习一项新技能的公式** 一项新技能=(得核心技巧)+(入门)+(固定.持续.大量的训练)一项新技能=(得核心技巧) +(入门)+(固定.持续.大量的训练) 一项新技能=(得核心技巧)+(入门)+ ...

  2. 年轻就该多尝试,教你20小时Get一项新技能

    LZ作为一个很喜欢体验的人来说,总想什么都尝试一下(这个世界这么慷慨,不多体验下多亏!),体验了这么多东西,发现,其实很多东西入门其实都不难的.我总是劝我身边的人多去体验一下新鲜事物,也一直想写这篇文 ...

  3. AI时代,产品经理需要掌握的5项新技能

    不同于传统的产品经理,AI时代的产品经理更加注重的如何将技术应用在业务问题上.AI时代,产品经理最重要的职责就是提供数据规范,所以这也要求产品经理对数据有足够的认识.文章对AI时代产品经理需要掌握的新 ...

  4. 如何快速学会一项新技能?

    周末陪我三岁的儿子学骑自行车,之前一直用辅助轮,这次想直接去掉辅助轮骑.结果我就搀扶了不到一分钟,他就学会了. 在感叹小朋友学习能力强的同时,我在思考,为什么小朋友能这么快学会一项技能.是否有通用的方 ...

  5. 听说小爱偷偷学习了一项新技能

    昨天520,网络情人节,朋友们都收获表白了吗?

  6. 学习新技能时,大脑在如何发生改变?

    来源:中国生物技术网 众所周知,无论是一项运动.一种乐器还是一门手艺,掌握一项新技能都是需要花费时间并进行训练的.虽然我们都知道健康的大脑能够应付的来,但是为了开发出新行为大脑如何发生改变科学家们对此 ...

  7. 高效掌握新技能的「树型思维」

    大家好,我是Z哥. 不知道你有没有过这样的困惑,想学习某项新技能,但是很容失败.比如,出于职业发展的考虑,想学习一门新的编程语言,或者想了解一个新的技术框架:又或者看了某些综艺节目后想玩一玩滑板.练一 ...

  8. 2020年,JavaScript开发人员必备的5项高薪技能

    全文共1816字,预计学习时长5分钟 图源:unsplash 开发人员的一生可以用两句话概括:计算器,以及学习新技能.成为开发人员绝非易事,他们是解决问题的人,也是不断学习的人.科技世界每天都在快速变 ...

  9. 独家 | 成功开发者必备的5项软技能

    作者:Marisa Hoenig 翻译:王可汗 校对:欧阳锦本文约2000字,建议阅读6分钟 本文介绍了除了扎实的编程能力之外,成功开发者必备的5项软技能. 标签:编程 一次又一次的面试失败,我感到很 ...

最新文章

  1. 微博:推动世界的力量(第2版)
  2. Java NIO系列教程(八) SocketChannel
  3. 算法之数论应用篇(二)
  4. 2013 ACM/ICPC Asia Regional Changsha Online - C
  5. 谷歌发布 iOS 黑客工具软件,或导致 iOS 11 被越狱
  6. mysql limit 用法-分页
  7. 爬虫 requests模块的其他用法 抽屉网线程池回调爬取+保存实例,gihub登陆实例
  8. 下载各种在线视频及字幕
  9. 基于质谱的蛋白质鉴定,第3节:基于MALDI-MS肽指纹图谱的蛋白质质谱鉴定
  10. 抓不到作弊学生就集体扣分!澳洲国立大学计算机系300多人被降分停课
  11. 石油工程课程设计c语言,东北石油大学-石油工程抽油设计C语言编程.doc
  12. AT指令(中文详解版)(一)
  13. word页眉添加横线与删除横线
  14. opc ua 用哪种语言编写_OPC UA是什么 OPC UA简介
  15. 使用163邮箱发送邮件报错(554, b'DT:SPM 163 smtp3,G9xpCgCHi5RJOFVemMZ4Dw--.348S3 1582643274,please see http://ma
  16. wpa_supplicant 常用操作
  17. 关于comparator升序、降序
  18. 动态规划解决最长公共子序列
  19. 财务部门:OKR 案例集
  20. 手机端软件 小界面有“大江湖”

热门文章

  1. 评论设置----第二章:创建和管理内容
  2. mysql排行榜sql的实现
  3. Tools_将Python脚本封装成exe可执行文件
  4. 珍惜那些爱你的人,不要令他们失望,加油吧,我们。
  5. noclobber属性
  6. 解决This application failed to start because no Qt platform plugin could be initialized问题
  7. 【远程操控】Pycharm配置远程连接服务器
  8. pls-00302: 必须声明 组件_手把手教你开发vue组件库
  9. 解决vs2010下不能创建项目及文件的问题
  10. 用存储过程还原数据库