用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好的一個原因。
原創:曹磊(Leo Cao) Email: [email protected]。若轉載,請標明出處。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章