2016年4月29日 星期五

Android Studio 2.0 舊電腦記憶體調整記錄

我的一台雙核心4G ram 的老舊電腦,近日執行android studio, 編譯或執行的時候, 有時會慢到整個電腦都卡住的感覺, 查看電腦的ram, 發現studio本身大概最多會佔到800M的空間, 但執行編譯時, 有個java.exe 經常會佔到2G以上的空間, 只要發生這種情況, ram的佔用率大概就是99%左右. 然後就算編譯個一個小時, 也跑不出結果來, 我猜想可能是記憶體佔用太高了, 造成系統整個卡死了, 所以開始嘗試解決的方法.

我主要是參考以下這篇: 照著調整完以後, 果然有效, 調整之後, 新編譯的時間, 降低到十到十五分鐘可完成, 配合instant run, 勉強可以用來開發android 的 app.

Android studio takes too much memory

第一部分

首先, 先減少android studio 本身所佔有的ram, 到File/Settings/Plugins 內把以下的部分disable 掉. 

  • CVS Integration
  • Git Integration
  • GitHub
  • Google Cloud Testing
  • Google Cloud Tools Core
  • Google Cloud Tools for Android Studio
  • hg4idea
  • Subversion Integration
然後修改.vmoptions  這個檔. 把max heap size 改成 512MB:
-Xmx512m, 但是據原作者說, 改這個會造成Android Studio 有lag的現象, 所以我沒有改這一項. 

第二部分

改Gradle所佔有的ram, 在工作管理員中, 看到的java.exe, 據原作者說, 就是Gradle所佔用的記憶體. 它經常會在build程式碼的時期, 佔用將盡2G的空間, 修改方法如下


1.打開Android Studio 相關的project

2.在 Gradle Scripts之下, 打開gradle.properties這個檔, 把org.gradle.jvmargs=開頭的這一行的註解符號拿掉, 因為不加這一行限制的話, 它的預設是10248m,我有沒有看錯, 那不就是10G嗎? 我將它改成 -Xmx1024m, 原作者是改成只有256m, 據他說:改成256m也看不出對效能有何影響. 我想先給1G, 如果記憶體還是不夠, 再回來改小一點. 原作者還說改完這一項要重開Android Studio, 確定舊的process被kill掉, 套用新的設定.(如果改成512m, 會造成產生 release 版的 apk 時, ram 不足的現象, 出現java.lang.OutOfMemoryError: Java heap space, 所以還是改回1G)


第三部分 修改avd模擬器的ram大小, 這部分我原來就只有512M, 所以沒有更改. 

第四部分 是原文沒有提到的部分, 那就是dex 的Max HeapSize, 因為我照著上面修改之後, 速度還是很慢, 沒什麼改變. 觀察工作管理員, 還是有一個佔大約2G的java.exe項目, 我就想著這個佔2G的東西到底是什麼, 我想到在build.gradle裡曾設定如下:


dexOptions {
    javaMaxHeapSize "4g"}





於是我就把4g改成1g, 果然改過之後, 那個工作管理員上, 原來是2G(雖然我原來設4g, 但實際上2G可能是極限了, 因為我全部記憶體也才4G而已)的java.exe, 立刻變成1G, 但是即使如此速度還是很慢, 於是我又把1G改成2G, 速度才有所提升. 因此我想也不能改太小, 2G太概就是理想值吧! 

Read more...

2016年4月27日 星期三

分享android studio 快捷鍵使用心得 shortcut

剛使用android studio 印象最深的是它提供相當多很好用的快速鍵, 網上寫的快按鍵 (shortcut), 都太簡單了, 沒有實際用過, 太部分都不知所云, 這裡列出我用過且瞭解的快捷鍵說明, 因為不是抄來的, 所以都是自己的心得, 如果有我自己誤解的地方, 請見諒. 

Ctrl+F7 : 可以查詢當前游標所在元素(只有有效元素, 如變數或函數可以, 指令或註解內的文字不行)在目前文件中有參考到的地方,然後按F3可以查下一個, shift+F3反向查詢, 定義的文字查不到, 定義要用Ctrl+B (參看下面說明)

Ctrl+Shift+F7 : 可以高亮度標記當前游標所在的文字(任何文字均可, 含註解內的文字), 在目前文件中所有相同的文字, 然後按F3可以查下一個, shift+F3反向查詢, 按ESC(二次?)可解除

Ctrl + B : 跳到當前游標所在元素的定義位置, 如果abc是個變數, 那麼 int abc 就是定義; 如果abc是個函數(方法,method), 那麼 public void abc() {....} 就是定義, 另外一個更好用的方法是, 如果按住Ctrl再將游標移到變數或函數的位置, 會出現一個懸浮視窗, 內容是該變數或函數的定義內容. 如果只是想查看一下定義的內容, 這樣就不必切換到變數或函數定義的位置再切換回來.

以上這三個(Ctrl+F7, Ctrl+Shift+F7, Ctrl+B), 查找相關變數或函數很好用, 以前我的作法, 都是用Ctrl + F 去搜尋, 用這幾個簡單多了, 而且Ctrl+Shift+F7還可以高亮度標記, 看起來更清楚.

Ctrl+Alt+B 查看interfaces所有的實現方法之定義.

Alt + Q : 查看當前游標所在的函數名稱, 有時函數寫太大了, 看不到函數的開頭名稱, 會搞不清楚目前修改或查看的是不是想要的函數, 又或者類似的程式碼, 但有多個不同的函數, 怕不小心改錯地方. 除了用Alt + Up或更笨的方法用scroll bar去移到函數開頭去確認之外, 這個應該是更聰明快速的方法了.

Ctrl + Z : undo 大家都知道, 但是 redo 呢, eclipse 是 Ctrl + Y, 但android studio, 是Ctrl + Shift + Z, 網上大都沒提到, 我也沒想到, 試了Ctrl + 各個字母都不是, 找了好久, 才查到.

Ctrl+Alt+Left(箭頭向左鍵)/Right(箭頭向右鍵) : 回到上次瀏覽的位置, 在瀏覽位置間切換

Alt + Up(箭頭向上鍵)/Down(箭頭向下鍵) : 移動到上個函數或下個函數
Ctrl+[ :到大括號的開頭處; Ctrl+] :到大括號的結尾處, 對搞不清楚大括號那個跟那個配的情況很有幫助.(Ctrl + W也有類似的效果, 下面有說明)
Ctrl+Shift+Backspace:可以跳轉到上次編輯的地方


Ctrl + E 列出最近曾開啟過的文件

Ctrl+Shift+N  用打字搜尋, 快查任何一個檔案 省去從一大堆檔案中去找的困擾, 且可以用*?查詢, 如*activity*.java, 快擊兩下滑鼠, 可開啟該檔,

連按2次shift快查任何檔案內的任何文字.

Ctrl + Shift + F 也可以查任何檔案內的任何文字. 但可以加更多搜尋條件. 

Ctrl+Shift+V : 這個shortcut用來從多個剪貼內容選取貼上. Ctrl + V是貼上剪貼簿內容, 大家都知道, 但android studio 還支援記錄多個複製內容, 選取其中一個貼上.

Ctrl + W : 逐漸擴大選取範圍. 第一次按下Ctrl + W 會先選取一個字(word), 再按一次, 會向左右再擴展一個字, 第三次按下, 會擴展選取一整行, 然後再按一次, 會再擴展到一個大括號的內容, 再按一次, 再往外擴展到另一個更外層的大括號的內容, 到最後則是選取整個文件內容. 我常用這個快捷鍵選取大括號的內容, 用於複製到別處, 或刪除某一段括號內的程式碼, 特別是當大括號的層次太複雜, 找不到開頭與結尾時, 特別好用.

Alt+F8 用來顯示一個表達式, 變數的值, 先選取一個表達式或變數, 可以配合上文所用的Ctrl + W來選取. 再按下Alt+F8, 會彈出一個視窗,視窗內有該表達式的值, 這個在除錯時, 用來觀察變數的值. 因為下方除錯視窗太小了, 觀察變數的值, 不是很方便. 用這個比較清楚. 另一個快速鍵也有類似功能, 除錯時, 先按住Alt, 再用滑鼠去點變數:會出現一個懸浮視窗, 也會呈現變數的值, 這個使用起來也很方便.

Ctrl + O 顯示class內, 可以被Override的函數.

Ctrl + I 顯示可以被Implement的函數

F11 加入bookmark
Shift+F11 顯示所有書籤
Ctrl+F11 加書籤標記
Ctrl+ 數字 跳到第幾個bookmark位置

Alt + Ctrl + T 將一段代碼用try...catch, if...else, while...等結構包起來

Ctrl+shift+I 不離開當前文件的情況下快速查看某個方法或者類的定義內容

Alt+F7 查找函數或物件調用的位置 (分類)
Ctrl+Alt+H 查找函數或物件結構層次

Ctrl+F12 查看類的方法結構


Ctrl+shift+A 快捷鍵搜尋
Ctrl+P 顯示出某方法函數所需要的參數。

Read more...

2016年4月19日 星期二

Android studio Instant run與multidex的奮鬥記

話說,我android的開發機器是一部雙核心的ibm r61筆電, 有4G的ram t8300 cpu, 跑eclipse是還算順暢, 本以為這樣子用, 可以撐上一段時日, 但好景不常, 隨著我的專案愈寫愈大,有一天可怕的事發生了, 那就是65536的惡夢, 原來android有限制不能寫超過65536個函數。

65536, 我又不是在開發windows 10或android 6。 怎麼可能會超過65536個函數. 原來不是這樣算的, 要把所有用到的jar都算進去。那些加入基本的 jar 動不動就七千八千。還有的1萬2萬的, 隨便一加總就超過65536了。

我開始想辦法解決,方法是把dex拆成多個,這樣就不會超過65536,所以稱為multi dex,但在eclipse上面真的解法都很麻煩,試了很多方法都不行,好不容易找到一個最簡單的方法,就是套用別人做好的方案,也成功了,但最後要做release版的時候,又出了問題,怎麼都無法克服。終於只好轉移到android studio。

本來真不太想用android studio 的。原因是電腦等級不夠,曾經安裝了一次,試了試,實在是跑不太動。後來又移除了,雖然比eclipse好用。但eclipse用熟了, 其實也還好. 但這一次實在是被multidex的問題給搞慘了。本來用eclipse處理multidex已經成功了99%了, 但最後用proguard產生apk時, 遇到問題居然一直無法解決。只好又重新安裝了android studio , 但沒想後來的專案, 又加入了一個相當大40mb的 jar 包,一放上去用 android studio 編譯執行的速度,真的是慢到無法忍受, 每次改個程式碼, 關掉所有的程序, 只留android studio都要跑個十幾分鐘,如果再開個瀏覽器,跑半個小時,都出不來。本來想放棄, 再重回eclipse的懷抱,再與muti-dex奮鬥一次。

 就在此時救星出現了,Android Studio 1.5 提示我有新版的2.0可更新,我查看有何新功能,救星就是新版的Android Studio 2.0 內的Instant Run。Instant Run 顧名思義,就是快速run,所謂快速,就是每次更改程式碼,Instant Run 只針對修改的部分編譯,然後就可以執行了,不必每次都重來。每次從編譯到執行時間,都是用秒計算的,當然可以省很多時間,這真是老電腦的福音。

我又找了許多資料,大概明白Instant Run的作法,你如果不會使用,建議參考這一篇,算是蠻詳細的。開發速度快 50 倍:詳解 Android Studio 2.0 的殺手功能 Instant Run


當我一步一步照著做的時候,出現一個錯誤訊息如下:

Instant Run is disabled: Instant Run does not support deploying build variants with multidex enabled, to a target with API level 20 or below. To use Instant Run with a multidex enabled build variant, deploy to a target with API level 21 or higher.

又扯到multi-dex,我就是因為這個multi-dex的問題才投到Android Studio的陣營來,現在又看到這個,看來好像很嚇人的樣子, 不會是因為我用到multi-dex 不能用instant run吧. 趕快google一下這個訊息。


在這一篇提到:

http://stackoverflow.com/questions/35405040/cannot-instant-run-legacy-multi-dex-on-dalvik-runtimehttp://stackoverflow.com/questions/35405040/cannot-instant-run-legacy-multi-dex-on-dalvik-runtime

In order to activate multiDex at old android versions you have to set multiDexEnabled to true, add dependency and extend your application class from MultiDexApplication or launchMultiDex.install(this) in your application class, which will cause legacy multiDex installation.

However since Intant Run can't work with legacy multiDex you have to use normal one. All you need is removing all that code above except of multiDexEnabled flag set to true. This method is only supported by devices with API 21 and above.

依他的說法, 要把之前改成可以用multi-dex的部分還原, 只留multiDexEnabled 設成true這一部分, 那這樣子, 還能保有multi-dex的功能嗎? 那我還不如回eclipse好了。


不死心, 再找看有沒有別的解法:
開發速度快 50 倍:詳解 Android Studio 2.0 的殺手功能 Instant Run
提到:

1.將 minSdkVersion 改成 21
2.或是將專案根目錄下 build.gradle 的 gradle dependency 改回
classpath 『com.android.tools.build:gradle:1.3.0』 ,當然,這樣就沒有 Instant Run 的能力了
3.等官方釋出新的版本

很顯然的, 這些都不是答案, 因為將 minSdkVersion 改成 21, 那android 4.X不就全放棄了嗎

再找, 又找到這一篇:

instant run can't support multidex

提到InstantRun does support multidex out of the box when targeting Emulator or Devices that are are least API 21 (Lollipop or Marshmallow). Are you trying to target a device with 19 during development ?

沒錯,我用target device並非api 21 以上的機器,我是用android 4.2的手機, 當測試機。於是我改用genymotion,並找一個api 21, android 5.0的模擬器版本來用。 測試一下, 果然一切都正常,而且什麼minSdkVersion,什麼MultiDexApplication,我都沒更動,就可以直接用instant run了,原來只要測試用的手機不使用android 5.0以前的版本,就可以在multidex下,使用instant run。不瞭解為什麼前面幾文章,寫得如此複雜。測試結果,雖然不像別人說的,每次使用instant run 只花二秒三秒。但從來也沒超過一分鐘,大部分的時間都在20秒以內。這對我那台先前動不動就要跑個十幾二十分鐘的機器,我已經很滿意了。 

我到目前為止會造成全部重新編譯的情況有:
1.更換測試的手機 (因為很多dex檔案是放在手機根目錄內相關app的資料夾內)
2.解除已安裝的app
3.大幅度修改程式碼
4.adb device offline或unconected的時候

而修改res資料夾內xml的內容,我遇到的情況,還是會使用instant run,不會全部重來。


最後又看到這一篇,

Android 在 Multidex 下使用 Instant Run

有提到用gradle
使用gradle中的Build Variant可以做到不用每次都更改minSdkVersion還能使用Instant Run。
雖然不知為何要改minSdkVersion, 不過記下來當備忘, 以後也許會用到

不過雖然使用instant run沒什麼大問題,但也出現一些小問題:
1.曾出現原始碼, 除錯時,有對不起來的情況, 這時, 我在原始碼不符合的部分, 按enter加了一空白行, 再重debug, 就正常了。

2.也出現過新寫了個class, 編譯時都沒錯, 但執行時, 卻當在別的地方參考到此一class時, 出現找不到的情況, 同樣在那個class的程式碼, 加了個空白行, 再重run  也正常了

3.本來好像可以用instant run 但半途卻出現什麼apk找不到之類的, 也不知問題在那裡, 只好rebuild project, 但這一來就不是用 instant run , 而是全部重來了,但之後再使用時就正常了。


Read more...

2016年4月11日 星期一

實測最準確, 用cpdetector偵測unicode utf-8 big5 gbk 等檔案編碼

當讀取一個純文字檔時, 它的編碼為何, 一般是無法知道的, 這也造成許多亂碼的問題, 有些文件的檔首有標記可進行判斷, 事情會比較簡單, 但遇到無標記可判斷的文件, 要知道其編碼, 就有些麻煩了.
cpdetector一個可以自動檢測檔案編碼格式的項目, 經過實測其準確度頗高, 它是按照「誰最先得到探測結果,就以該結果為準」傳回探測的文件編碼。 它可以給一個網址, 來判斷該網址所指向的網頁編碼, 也可以給一個檔名, 用以判斷該文檔的編碼. cpDetector是採用統計原理,探測的結果並非完全正確。

以下只能判斷有標記的unicode相關的檔案, big5 gbk 等判斷不出來
    private String getCharset(String fileName) throws IOException {

        BufferedInputStream bin = new BufferedInputStream(new FileInputStream(
                fileName));
        int p = (bin.read() << 8) + bin.read();

        String code = null;

        switch (p) {
        case 0xefbb:
            code = "UTF-8";
            break;
        case 0xfffe:
            code = "Unicode";
            break;
        case 0xfeff:
            code = "UTF-16BE";
            break;
        }
        return code;
    }


以下是一段使用cpdetector 的 java判斷文件的範例
public static String getTextCode(File f) {

CodepageDetectorProxy detector = CodepageDetectorProxy.getInstance();
//ParsingDetector可用於檢查HTML、XML等文件的編碼,false不顯示探測過程的詳細信息。
// detector.add(new ParsingDetector(false));

//為了增加準確性,採用多個探測器,增加探測器不會增加執行時間,
//因為detector按照「誰最先返回非空的探測結果,就以該結果為準」不會繼續執行其他探測.

// 如果是unicode的文件, ByteOrderMarkDetector可快速檢測
detector.add(new ByteOrderMarkDetector());

//JChardetFacade封裝了由Mozilla組織提供的JChardet,它可以完成大多數文件的編碼
//測定。所以,一般有了這個探測器就可滿足大多數項目的要求,如果你還不放心,可以
//再多加幾個探測器,比如下面的ASCIIDetector、UnicodeDetector等      
detector.add(JChardetFacade.getInstance());
detector.add(ASCIIDetector.getInstance());
detector.add(UnicodeDetector.getInstance());

java.nio.charset.Charset charset = null;
try {
charset = detector.detectCodepage(f.toURI().toURL());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

String a = charset.name();
return a;
}


cpdetector會用到三個JAR包:antlr.jar、chardet.jar和cpdetector.jar


如果需要對網址進行網頁編碼判斷, 使用detector.detectCodepage指令, 請參考以下:
https://segmentfault.com/a/1190000004408835

Read more...

2016年4月10日 星期日

在android studio中, 對package name改名

記得以前用eclipse的時候, 對package name更名, 是很簡單的一件事, 好像
有一個地方是專門用來改package name的, 而且只要做一個動作就可
以了, 但是換到 android studio 時, 好像只能從refactor, rename 去更改, 我照著 http://stackoverflow.com/questions/16804093/android-studio-rename-package 
中第一個提到的方法去做, 好像很不順利, 不知是否忽略了什麼地方.

後來改用第二個方法去做, 雖然有些麻煩, 但終究改成了, 測試也沒什麼
問題. 原文如下:

Another good method is: First create a new package with the desired name by right clicking on the java folder -> new -> package.
Then, select and drag all your classes to the new package. Android Studio will refactor the package name everywhere.
Finally, delete the old package.
Done.
One more thing very important
You have to Change manually Android Manifest and gradle file to the new package if you use this method.
以上做法, 簡而言之, 就是先建立一個新 package, 再把舊 package 的 class
 都搬到新 package之下, 最後再把舊的空的 package delete 掉.
我實際使用時, 除了要手動更改 AndroidManifest.xml and 及 build.gradle  
之外, 還要注意, java 程式碼中, 用到 import old.package.R 的地方, 不會自
動改成 import new.package.R, 要手動去改. 最好用
 edit -> find -> replace in path去找, 然後一個一個去確認替換, 就只要找
*.java 的檔就好. (R.java內的不用改, 它會自已產生)
完成後, 先 clean project 再 rebuild project 最後再去 run. 我用的 android studio
是1.5.1的版本. 如果不同版本, 有不同做法, 或與我描述的不同, 請自行斟酌使用.

附帶一提的是在play store 中上架之後的package name就不要再改了, 因為它
不讓你上傳不同 package name的 apk 檔, 我就是改過一次, 結果
 play store console 不讓我上傳, 只好花時間, 又改回來, 真是搬磚砸腳, 自討苦吃.

Read more...

2016年4月8日 星期五

genymotion android 虛擬機與host 電腦 共享資料夾的方法

怕下次忘記找不到, 記錄如下:

實際測過是可行的


Try this.

Go to your VirtualBox VM setting(設定值) / Shared folder(共用資料夾), 按+號 Add a shared folder with the folder you want to share(加入你要共享的資料夾), and check the "auto mount" and "permanent" options(自動掛載和設為永久要勾選)

Start your VM as usual from the Genymotion software

Your shared folder is available in the /mnt/shared directory (multiple shared folders are supported)( 在/mnt/shared資料夾, 就可看到共用的內容了)

Source: http://stackoverflow.com/questions/18530114/accessing-files-from-genymotion-sd-card

特別留意的是, 如果 android genymotion虛擬機是在開啟的狀態下 設定, 則必須關掉重開,  共享資料夾才會生效.

Read more...

如何得知proguard是否成功混淆原始碼

Android由於其代碼是放在dalvik虛擬機上的代碼,所以能夠很容易的將其反編譯為我們可以識別的代碼。所以可以利用dex2jar, JD-GUI工具來查看代碼, 看proguard是否成功混淆原始碼.

方法如下:
首先先找到反組譯的apk檔,請將apk解壓, 產生一個classes.dex的檔案

下載dex2jar
https://sourceforge.net/projects/dex2jar/

執行 d2j-dex2jar.bat "classes.dex", 然後產生了classes_dex2jar.jar

下載JD-GUI
http://jd.benow.ca/

打開classes_dex2jar.jar就可觀看原始碼

如果像以下, 很多內容都變成a b c d....就是proguard成功混淆代碼了

  public static com.docsearcher.index.h a;
  public static File b;
  public static Integer c;
  public static Integer d;
  public static TextApp r = (TextApp)TextApp.a();
  public static int u = -1;
  public static boolean v;
  public static boolean w;
  private com.google.android.gms.ads.h A;
  private TextView B;
  private com.docsearcher.index.f[] C;
  private ImageButton D;
  private ImageButton E;
  private ImageButton F;
  private ImageButton G;
    this.M = paramInt;
    this.f.f = 0.0F;
    System.gc();
    this.k = this.i.a(localObject, this.l);
    this.q = (Integer.toString(this.k.curHit + 1) + "/" + Integer.toString(this.k.maxHit));
    this.o.setText(this.p + ":" + this.q);
    this.f.v = this.k;
    this.g.b = this.k;
    this.f.c = this.k.contentString;
    this.f.d = ((File)localObject).toString();
    this.I.b.getCurrentItem();

proguard的用法請參考

Android Studio 如何使用 Proguard 進行代碼混淆

Read more...

Android Studio 如何使用 Proguard 進行代碼混淆

 參考這個:
http://developer.android.com/intl/zh-tw/tools/help/proguard.html


其中最主要的是修改app目錄下build.gradle這個檔:

1.以下的 minifyEnabled 一定要設為true
2.還有把proguard的規則寫在app目錄下proguard-rules.pro這個檔.這是因為以下的設定:

proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

3.如果Android Studio處理proguard的過程中出現 out of memory 的問題, 加以下內容:
dexOptions {
        javaMaxHeapSize "4g"

    }
4.出現 'META-INF/LICENSE.txt'或其他檔案重覆加入的問題, 加以下內容:

    packagingOptions {

        exclude 'META-INF/DEPENDENCIES.txt'
        exclude 'META-INF/LICENSE.txt'
        exclude 'META-INF/NOTICE.txt'
        exclude 'META-INF/NOTICE'
        exclude 'META-INF/LICENSE'
        exclude 'META-INF/DEPENDENCIES'
        exclude 'META-INF/notice.txt'
        exclude 'META-INF/license.txt'
        exclude 'META-INF/dependencies.txt'
        exclude 'META-INF/LGPL2.1'    }


build.gradle完整檔案內容如下:

apply plugin: 'com.android.application'

android {

    dexOptions {
        javaMaxHeapSize "4g"    }

    buildTypes {
        release {
            minifyEnabled true

            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-project.txt'        }
    }

    packagingOptions {
        exclude 'META-INF/DEPENDENCIES.txt'
       exclude 'META-INF/LICENSE.txt'
        exclude 'META-INF/NOTICE.txt'
       exclude 'META-INF/NOTICE'
        exclude 'META-INF/LICENSE'
        exclude 'META-INF/DEPENDENCIES'
        exclude 'META-INF/notice.txt'
        exclude 'META-INF/license.txt'
        exclude 'META-INF/dependencies.txt'
        exclude 'META-INF/LGPL2.1'    }
}
}


轉換到android studio, 使用proguard時, 我把 minifyEnabled 忘記改true了, 所以每次檢查代碼都未混淆. 特別寫下本文, 提醒自己.

proguard是否有作用, 請參考以下文章


如何得知proguard是否成功混淆原始碼


Read more...

2016年4月2日 星期六

Unable to execute dex: method ID not in[0, 0xffff]: 65536 在eclipse最簡單的解法

如果可以用android studio此問題可更簡單的解決, 但非要用eclipse時, 就真的很麻煩, 網路找到最簡單的解法, 就是套用別人寫好的方案. 說是簡單, 但其實還是遇到很多挫折. 所以還是建議用android studio比較簡單.


 當我們的程式碼過大時,編譯時會報Unable to execute dex: method ID not in[0, 0xffff]: 65536)錯誤。當出現這個錯誤時說明你程式碼含有的太多的方法,或者你引用的第三方jar包有太多的方法,這兩者的方法加起來已經超過了65536這個數目。
以下基本參考下列文章, 加上自己實作的補充:

到此頁面下載, 並按其說明實作



Step1: 複製以下兩個檔案到android project的根目錄下

Dex65536/custom_rules.xml
Dex65536/pathtool.jar
Copy these two files in your android project, and execute the following command to generate build.xml.
到如下adt的目錄
cd D:\adt-bundle-windows-x86-20140702\sdk\tools在命令列, 執行下列
android update project --target 2 -p "D:\My Documents\AndroidApp\docSearch"命令
因為還有用到
google-play-services_lib(在另一個單獨的project), 所以還要加上這個
android update project -p "D:\My Do
cuments\AndroidApp\google-play-services_lib"
(以上 -p 後接專案根路徑, --target 2 , 其中的的2是在D:\adt-bundle-windows-x86-20140702\sdk\tools執行 android list targets, 得到的值.(id: 2 or "android-22")
http://developer.android.com/tools/projects/projects-cmdline.html#UpdatingAProject)

Step2: add some code

You need to add some code to load the secondary .dex file before your application starts.
public class App extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
// copy dexTool() method into your own custom Application and call it after super.onCreate().
        dexTool();
    }

    /**
     * Copy the following code and call dexTool() after super.onCreate() in
     * Application.onCreate()
     * 
     * This method hacks the default PathClassLoader and load the secondary dex
     * file as it's parent.
     */
    @SuppressLint("NewApi")
    private void dexTool() {

        File dexDir = new File(getFilesDir(), "dlibs");
        dexDir.mkdir();
        File dexFile = new File(dexDir, "libs.apk");
        File dexOpt = new File(dexDir, "opt");
        dexOpt.mkdir();
        try {
            InputStream ins = getAssets().open("libs.apk");
            if (dexFile.length() != ins.available()) {
                FileOutputStream fos = new FileOutputStream(dexFile);
                byte[] buf = new byte[4096];
                int l;
                while ((l = ins.read(buf)) != -1) {
                    fos.write(buf, 0, l);
                }
                fos.close();
            }
            ins.close();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        ClassLoader cl = getClassLoader();
        ApplicationInfo ai = getApplicationInfo();
        String nativeLibraryDir = null;
        if (Build.VERSION.SDK_INT > 8) {
            nativeLibraryDir = ai.nativeLibraryDir;
        } else {
            nativeLibraryDir = "/data/data/" + ai.packageName + "/lib/";
        }
        DexClassLoader dcl = new DexClassLoader(dexFile.getAbsolutePath(),
                dexOpt.getAbsolutePath(), nativeLibraryDir, cl.getParent());

        try {
            Field f = ClassLoader.class.getDeclaredField("parent");
            f.setAccessible(true);
            f.set(cl, dcl);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

}

Step3: ant build and run

Make sure you have ant installed.
cd /YourProject
ant clean debug install run
ant debug install rund (不clean且進入debug 偵錯)
ant run (直接run, 不compile)

其他注意事項:

   

1.eclipse 中 Run as-> Ant build 未出現的解法

 in eclipse :1. Help -> Install New SoftWare
  1. Work With -> "http://download.eclipse.org/releases/juno"
  2. Drop down list "General Purpose Tools"
  3. select "Eclipse Plug-in Development Environment"
After doing this...eclipse restart, then show option of Ant Build in Run as


2.使用ant遇到invalid resource directory name: res crunch

這是因為ant無法處理crunch資料夾

1.先把Eclipse中[Project]-->[Build Automatically]關掉(否則crunch資料夾會一直被自動生成)
2.將bin/res/crunch刪除

Read more...

  © Blogger templates Psi by Ourblogtemplates.com 2008

Back to TOP