Gradle 構建 android 應用常見問題解決指南

yangxi_001發表於2014-03-21

前言

android gradle 外掛已經發展到0.5.7,同時gradle 本身也到了1.8,相比兩個月前,android gradle 更快,更完善,也更好用了,為了讓各位androider 早日用上gradle這樣的神器,特地寫一篇關於gradle一些奇葩錯誤的解決指南.

使用最新的gradle android外掛

以前我們寫的時候會這麼寫

dependencies {
    classpath 'com.android.tools.build:gradle:0.5.0'
}

不過,由於android gradle 外掛的開發還是很活躍的,而且目前而言,可能還存在一些我們不知道的坑,但是,別人踩過,後邊,官方修復,為了不踩坑,我建議android gradle 始終保持最新版本,寫法如下:

dependencies {
    classpath 'com.android.tools.build:gradle:0.5+'
}

由於程式碼編碼與編譯環境編碼不一致,導致構建失敗

有時候,我們的程式碼使用utf-8 儲存的,但是,進行gradle build 的環境是gbk這類的,這時候會包如下錯誤:

15: 錯誤: 編碼GBK的不可對映字元

     * 鍑虹幇涓枃璇鋒敞鎰?

這個時候我們就需要手動的設定編譯時編碼型別.

tasks.withType(Compile) {
    options.encoding = "UTF-8"
}
apply plugin: 'android'
android {}

android support v4 重複引用問題

UNEXPECTED TOP-LEVEL EXCEPTION:
java.lang.IllegalArgumentException: already added: Landroid/support/v4/app/Activ
ityCompatHoneycomb;
        at com.android.dx.dex.file.ClassDefsSection.add(ClassDefsSection.java:12
3)
        at com.android.dx.dex.file.DexFile.add(DexFile.java:163)
        at com.android.dx.command.dexer.Main.processClass(Main.java:490)
        at com.android.dx.command.dexer.Main.processFileBytes(Main.java:459)
        at com.android.dx.command.dexer.Main.access$400(Main.java:67)
        at com.android.dx.command.dexer.Main$1.processFileBytes(Main.java:398)
        at com.android.dx.cf.direct.ClassPathOpener.processArchive(ClassPathOpen
er.java:245)

出現這個問題的原因一般是由於我們這樣的寫法導致:

dependencies {
    compile fileTree(dir: 'libs', include: '*.jar')
}

某個相同的jar包,被複制到了build目錄導致重複編譯使編譯時失敗,

由於這個問題android support v4 出現的比較多,所以同型別的都歸類為v4 問題吧.

要避免這個問題,我們儘量少使用依賴某個目錄下所有包,畢竟android專案不想java web專案動不動就有好幾十jar 包依賴.要修復這個v4,原理很簡單,可以使用依賴maven的寫法.

dependencies {
    compile 'com.android.support:support-v4:13.0.0'
}

打包後缺少*.so檔案

用指定依賴包的方式打包,我們會發現,最終打包後的jar沒有了*.so檔案,這個時候,我們需要自定義一個tasks,寫如下:

task copyNativeLibs(type: Copy) {
    from(new File('libs')) { include '**/*.so' }
    into new File(buildDir, 'native-libs')
}

tasks.withType(Compile) { compileTask -> compileTask.dependsOn copyNativeLibs }

clean.dependsOn 'cleanCopyNativeLibs'

tasks.withType(com.android.build.gradle.tasks.PackageApplication) { pkgTask ->
    pkgTask.jniDir new File(buildDir, 'native-libs')
}

這樣,在編譯時,就會自動把libs目錄下的**/*.so 檔案複製到apk裡面了.

構建多渠道包

在最新版本的gradle 0.5.7 中,構建多渠道包比之前簡單多了,在以前,你需要這麼寫:

android {
    buildTypes {
         hiapk {
             packageNameSuffix ".hiapk"
         }
         playstore {
             packageNameSuffix ".playstore"
        }
     }
    sourceSets {
        hiapk {
            manifest.srcFile 'hiapk/AndroidManifest.xml'
        }
        playstore {
            manifest.srcFile 'hiapk/AndroidManifest.xml'
        }
    }
}

要替換某個型別的檔案需要自己手動寫,渠道多了,這程式碼量是可想而知的多,在0.5.7中,進行了一個約定規則,構建,渠道包你只需

android {
    buildTypes {
         hiapk {
             packageNameSuffix ".hiapk"
         }
         playstore {
             packageNameSuffix ".playstore"
        }
     }
    sourceSets {
         hiapk.setRoot('build-types/hiapk')
         playstore.setRoot('build-types/playstore')
    }
}

在專案的根目錄下建立一個build-types的目錄,在建立對應渠道的子目錄,然後把一些,諸如要替換AndroidManifest.xml,裡面友盟渠道號什麼的,直接把xml複製進去就行,gradle在構建專案的時候,會自動的優先使用build-types下目錄檔案的目錄,諸如,根據不同渠道,不同國家換個程式圖示什麼的,都只要放到目錄下即可.

作者:遊戲阿柴 
出處:http://www.cnblogs.com/youxilua 

相關文章