用IntelliJ代替Eclipse,调试Android Source codes

    本文所说的调试Android Source Code,是指区别于一般的Android App,是对Android系统源代码,包括自带的Apps,比如Mms, Contacts, Dialer等的开发和调试,需要对IDE做特殊的配置。

    其实整个配置的目的,是2个方面:

    1,在调试的时候,可以看到相关代码的引用,即看到符号表,这样才可以step into进去debug。

    2,要能用remote debug的方式,attach到手机上运行的那些app的process上,比如com.android.mms。这就是区别于一般Android app调试的方面。

    用Eclipse调试Android Source Code,可以说是标准的Android开发的做法,如何配置,参考:http://source.android.com/source/using-eclipse.html

    但是Eclipse太慢了,在编辑输入的时候,那个一个字符一个字符蹦出来的感觉,真的是无法忍受。所以开始转向IntelliJ。Eclipse和IntelliJ的对比,可以Google下,有很多文章可以参考,而实际使用的体验,差别也是比较明显的。总的来说,Eclipse有点大,对于Android/Java的开发来说,不如IntelliJ专一,性能也是比后者差一截。如果我们想开发Android App,进行Java、或者Scala这样的JVM Lanauge(如何用Scala开发Android App是另一个话题),的开发,用IntelliJ是明智的。

    其实在Android的Source Code Tree中,有一些IDE的配置文件,在它的相对路径development\ide下,其中有Eclipse,IntelliJ, emacs 和 xcode的配置。在上面用eclipse的链接中,就提到了这个目录,用到了eclipse目录下的.classpath文件。

clipboard

    而对于IntelliJ来说,则不需要这个.classpath文件,只需要参考。而那个intellij子目录中的内容,我完全不知道如何用,本文的做法没有用到它们。

    虽然IntelliJ没有那个.classpath文件可以用,但是实际配置起来,也是不费事的。而且,它对android source code的那个编译输出目录out的依赖,也比eclipse的配置低多了。下面,直接上steps,在步骤中,我会说到和Eclipse的不同,以及一些tips:

    1,拿到整个Android Source Code,首先要编译成功,这会产生Android/out这个目录,IntelliJ和Eclipse相比,只需要其中的一个目录out\target\common\R。其实这个目录不是固定的,许多oem厂商,可以根据不同的configration,配置这个输出目录,这样实际的路径可能会是:out\xxxxx\target\common\R,总是,我们需要这个R。实际上IntelliJ可以自动扫描出来,我们到时候要勾选相应的这个路径。对比配置eclipse需要的那个.classpath,intellij降低了对out目录的依赖,这样的好处在于,由于out目录是会多变的,有时甚至需要删除它重新来过,所以还是尽量不依赖为好。

    2,启动IntelliJ 11.1.4,我们用Create New Project的方式。有一种情况,即用Open Project的方式,去打开一个已经存在的Eclipse项目。比如我们已经用那个.classpath文件,按照开头的链接,配置了Eclipse的环境,所以我们想用IntelliJ中兼容Eclipse项目的方式打开这个已经配置好的项目。不幸,这种方式是不行的,试验下来,intellij在open的过程最后,实际无法打开已有的eclipse项目。

clipboard[1]

[Update]在IntelliJ 12中,这个方式变化了:

clipboard[2]

    要用Import Project,然后直接选定android source codes的根目录:

clipboard[3]

    然后是:

clipboard[4]

    选择"Create project from existing sources",然后点Next。

clipboard[5]

    这里不用再选择IntelliJ Project的文件格式,然后Next,下面就接着第5步,开始扫描Sources。后面的截图就不更新了,类似的。

 

    3,好吧,即使之前已经按照eclipse的方式,配置了Android Source Code,没关系,IntelliJ的配置与之不冲突。现在点击Create New Project,开始下一步。

clipboard[6]

    这里,我们仍然不能选择第二项:“Import project form external model”,试图从已有的Eclipse项目中去创建。要选择第三项。next。

    4,选择好你的Android Source Code的根目录android所在的路径,已经起一个项目名称。这里好像intellij的project files location是可以和源代码分开放置的,实际上不行,第二项一定要设置为源代码所在的路径,后面会自动扫描其中的source files。第三项是intellij项目的文件格式,默认的就好。喜欢统一管理的,可以换成.idea子目录的形式。next。

clipboard[7]

    5,然后IntelliJ开始searching for soruces,耐心等待吧,可以去做下别的事情了,要等大约半个小时呢(当然这个也要机器的硬件配置)。其实如果熟练了,可以在这一步stop,然后自己选择要加入的module目录。

clipboard[8]

    6,自动扫描完成后,就会跳出来:

clipboard[9]

    默认是Mark All的,其实我们不需要这么多。所以先Unmark All,然后勾选我们需要的。这时,我们就可以参考那个.classpath文件了。

    打开这个文件,我们可以看到其中有2大部分, src和lib,其中src:packages/app, packages/providers, frameworks/base, frameworks/ex, frameworks/opt, frameworks/supports, development, libcore, external, 还有out下的那些;lib:主要就是out中的了,以及一个package中的lib。

    在这一步,我们只看src的部分,后面还要看lib的部分。

    所以根据我们的需要,packages/app中只需要部分勾选,development就全部不要选了,还有out中的内容,除了那个out/target/common/R要勾,其它的都不用,剩下的,我建议都勾上,因为基本都是公共的部分。记得一点,对于intellij的project来说,module越多,运行起来越慢,所以还是按需来选。将来也可以根据需要增减。

clipboard[10]

clipboard[11]

clipboard[12]

clipboard[13]

    请注意这个out/target/common/R,上面已经提到,这个路径有可能会由于oem修改了编译脚本而变化,请根据具体out的路径选择,但是intellij已经扫描出来了,只要辨识出来即可。

    另外,这个.classpath文件的内容,是随着android的升级,有可能变化的,请根据实际内容未准。

    再有,如果你还需要调试这个.classpath上没有列出的module,也可以在此时额外勾选相应的内容。

    比如,packages/apps/下,只选择了Mms和Phone。

clipboard[14]

clipboard[15]

    勾选好之后,next。

    7,开始searing library,又要等待了。

clipboard[16]

    8,自动扫描完成后,自动切换到如下界面:

clipboard[17]

    这里没有UnMark All的勾选,直接点选第一条,然后按shift,再点选最后一条(或者Ctrl +A,但IntelliJ响应很慢,因为条目很多),然后按下空格(这里要等待,IntelliJ的性能还要继续改进),来UnMark All。然后根据.classpath来勾选:

clipboard[18]

clipboard[19]

    然后next。

    9,开始searching for modules。还是需要等待一段时间,不过相比之前的2步,就短多了,因为我们之前勾选的sources不多。

clipboard[20]

    10,自动完成后,确定我们想创建的IntelliJ Modules。

clipboard[21]

    这一步里,就是上面我们勾选的sources,intellij根据source建立module,你也可以去掉某些source,这样也就无法在intelliJ中调试它们了。勾选的含义,intelliJ会在对应的目录下建立module文件.iml。

    如上图,common和common1,我们最好进行适当的改名操作。

    另外,我们需要去掉Base的勾选,因为我们只需要具体的base中的内容,比如base/core。

clipboard[22]

clipboard[23]

把刚才的那个Common修改成R。这是一个Tip。将来如果out被删除,要重新创建一个Module时,同样的路径,IntelliJ会命名为R,不再是Common了,所以这里事先修改为R,方便将来。

    另外,注意到这里R的实际路径是有变化的,多了一个caet2ur_qpl就是因为oem修改了编译的脚本所致。

    完成后,next。

    11,接下来,searching for frameworks。这一步也要等待一段时间。

clipboard[24]

    12,自动完成后,切换界面,intelliJ会显示出检测到的framework,这里都是Android类型的modules。我们只要看下,就可以点finish结束了。

clipboard[25]

    接下来,intelliJ会建立项目的索引,这同样耗时。等索引结束后,还需要做后面的配置修改工作。

clipboard[26]

    13,如果源代码中已经受vcs工具管理,比如git,就会出现这样的界面:

clipboard[27]

    我们就需要修改一些配置,去掉这些烦人的提示。

    在等待索引完成的时候,进一步的配置前,我们看看上面的操作对Android的代码树有什么影响:

clipboard[28]

    上面内容不是全部,简单的说,IntelliJ建立了项目文件.ipr和.iws,以及在我们勾选的module下建立了.iml文件。

    与eclipse相比,我觉得这是IntelliJ的缺点。eclipse除了使用那个.classpath文件之外,就没有再额外创建多余的文件了,intelliJ创建了多余的module文件,如果哪个module的代码混乱,从而被删除重新获取的话,那在intellij的项目里,就需要通过创建一个新的module的方式,来重新加入这个module。

    14,intelliJ索引完成后,我们先去掉刚才vcs工具的提示:

clipboard[29]

clipboard[30]

    左侧有一个Version Control,然后拖动右侧的滚动条到最下,去掉“Notify about VCS root errors”的勾选,然后点Apply。然后点击OK,关闭这个Settings界面。

    15,在左侧的Project Panel中点选任意一个,然后按F4,启动Project Structure界面,开始后面的配置。

clipboard[31]

    首先解决这个循环依赖的问题。鼠标移动过去,会有hints。

    1) 点选左侧的luni的main(可能已经被改名),右侧的dependencies中去掉对xml和davik的依赖。

    2) 点选左侧的core,右侧的dependencies中去掉对keystore, location, opengl, wifi, telephony, media, graphics, drm等的依赖,只保留libcore和R就行了。

    3) 点选左侧的opengl,去掉对graphics的依赖。

    4) 点选左侧的Filterfw,去掉对Filterpacks的依赖。

    5) 分别点选左侧的Wifi,Voip, Location, Media,去掉对Telephony的依赖(若存在的话)。

    经过上面的操作,Project Structure界面上的循环依赖的错误就没有了。

    16,修改依赖的顺序。注意到中间那些前面有+号的模块,它们是有AndroidManifest.xml的android模块(实际上,有的带+号的模块确实没有这个文件)。而没有+号的,实际上是Java模块,依赖的是Java的SDK。

clipboard[32]

    比如上图中的Calendar模块,它是一个android模块,所以它默认依赖的对象中,Android Framework是第一个,我们需要用最后侧的向下按钮,把对Android Framework的依赖降低到最后:

clipboard[33]

对每一个android模块,都要做这个动作。有点繁琐,呵呵。为什么要做这个呢?因为对于Android Source Code来说,它本身就有所有Android Framework的Source,所以对于已近安装好的Android SDK的依赖要降低优先级,这样Android Source Codes中会首先去找本身就带的实现,而不是Android SDK中的实现了。

    额外说一点,Core这个android模块,是核心的基础模块,也应该把它的顺序升高,放到最上面。而R模块应该仅次于Core模块。Core依赖的libcore,可以放到比Core还高的位置上。

    17,修改android模块的gen目录。IntelliJ会在每个android模块下创建一个多余的gen目录,这会导致Android Source Code的编译会有问题,我们可以把它们统一设置到out目录中。

    先看下多出来的gen目录,跟每个android模块的.iml是放在同一个目录下的。

clipboard[34]

    上面的内容不是全部。那在Project Structure界面中要做的修改(以上面的Calendar为例):

clipboard[35]

    去掉默认的勾选,选择下面那个“Use module compile output path”:

clipboard[36]

    然后点击Apply,再拷贝"Output path:"后的路径,打开Android的设置,切换到Compiler标签页

clipboard[37]

    将AIDL Compiler和AAPT Compiler的Destination directory的路径,除了最后的gen,前面的路径改为上面Output path中的路径,如下:

clipboard[38]

    然后点击Apply。若有提示不存在AndroidManifest.xml的警告,直接OK。

    后面对每一个Android模块都做同样的操作。

    全部做完后,关掉Project Structure界面,然后使用Linux的Shell命令清理掉已经存在的那些与.iml同目录下的gen目录。同时,查看out下的目录,会发现新设置的gen目录。

clipboard[39]

clipboard[40]

    18,现在,所有的配置都完成了,我们首先看看某一个模块中的代码能够是否能够找到相应的reference code。

clipboard[41]

    比如我们打开SmsManager.java这个文件,右侧都是蓝色或者黄色的颜色标示,这说明IntelliJ找到了这支源代码文件中调用了的其它API的实现,否则就会是红色标示,鼠标可以点击这些颜色标示,跳转到相应的地方。

    说明一点,Android Source Code中有一些只有lib的库,可能是看不到源代码的,所以无论你如何添加module,也是找不到的。

    19,下面,我们配置remote debug,然后,我们就可以调试Android System App或者Frameworks了。

clipboard[42]

    如上图,intellij已经自动建立好了2个debug的配置项,但是对于Android System App来说,是不需要的,可以删除它们。点击Edit Configurations进入debug的设置界面。右上那个按钮,就是attach到手机里的process进行debug时用的,前提是我们要先配置好debug的设置。

clipboard[43]

    在这个界面,首先删除IntelliJ自动建立的那几个配置项,然后点击+按钮,选择Remote:

clipboard[44]

    如上图,修改2个地方,1个是name,是一个port。为什么是8700?请看本文开头的链接中的内容。然后OK,退出。

clipboard[45]

    这时toolbar上的debug项也随着有了变化。接下来,打开android手机的usb调试,连接上pc,点击那个attach debug的按钮。首先是出现一个waiting for adb的进度条对话框,然后出现Choose Process的界面:

clipboard[46]

    上图表现的是手机没有连接上pc时的情况,连接上之后会自动刷新,如下:

clipboard[47]

    这里选择com.android.mms,表示想要调试android的系统自带的app Mms。点击Mms上的创建新消息的按钮,会挺在设置在onCreate的断点:

clipboard[48]

    OK,接下来,开始尝试step over, step into等调试操作。

clipboard[49]

    经过几步F8(step over),到达initResourceRefs()处,接下来,step into:

clipboard[50]

    intellij正常跳转到initResourceRefs()的实现处的第一行。

    OK,经过这个简单的示例,说明已经完全建立成功了在intellij上调试Android Source Code的环境。

    本文到此结束,最后来一些总结:

  1. IntelliJ比Eclipse的性能要高一个层次。在Eclipse上输入,以及Code Compelete都很痛苦。
  2. IntelliJ比Eclipse的配置要繁琐很多。
  3. IntelliJ比Eclipse要“智能” 不少,用用就知道了。
  4. IntelliJ打开那些已有git管理的代码,自动支持git在ide里的操作,而Eclipse的git管理方式大不一样,比较繁琐。
  5. 稍微分析下IntelliJ建立项目的后的动作,它使用一个indexing的功能,可能是它的性能比Eclipse好的一个原因。
posted @ 2013-01-04 14:16  Leo L.Cao  阅读(...)  评论(...编辑  收藏