從零開(kāi)始的Android新項(xiàng)目2 - Gradle篇

相信大家的項(xiàng)目用上gradle都已經(jīng)很久了,但用得如何呢?這里分享一下我的gradle腳本,大部分都是去年6月左右就開(kāi)始用上的,有一部分比如簽名的安全保存則是最近才自己動(dòng)手,做了令自己覺(jué)得還不錯(cuò)的方案。

module類型的區(qū)分

科普小結(jié),可能有些同學(xué)不太明白Java library module和Android library module是怎么區(qū)分的,其實(shí)就是個(gè)plugin的區(qū)別,在module的build.gradle中:

Android application module:

apply plugin: 'com.android.application'

Android library module:

apply plugin: 'com.android.library'

Java library module:

apply plugin: 'java'

版本號(hào)管理

如果只有一個(gè)application module還好,如果我們有多個(gè)module怎么辦呢?每次改版本號(hào)累不累?

解決方案就是在root里申明全局變量,可以在單獨(dú)的gradle里(比如新建一個(gè)dependency.gradle)申明然后apply from引用進(jìn)來(lái),或者直接定義在root的build.gradle中。

project.ext {
    applicationId = "com.xxx"
    buildToolsVersion = "23.0.2"
    compileSdkVersion = 23
    minSdkVersion = 14
    targetSdkVersion = 23
    versionCode = 1
    versionName = "1.0.0"
    abortOnLintError = false
    checkLintRelease = false
    useJack = false
    abortOnLintError = false

    javaVersion = JavaVersion.VERSION_1_8
    ...
}

在子module里面則使用rootProject.ext去進(jìn)行引用:

android {
    compileSdkVersion rootProject.ext.compileSdkVersion
    buildToolsVersion rootProject.ext.buildToolsVersion

    defaultConfig {
        applicationId rootProject.ext.applicationId
        minSdkVersion rootProject.ext.minSdkVersion
        targetSdkVersion rootProject.ext.targetSdkVersion
        versionCode rootProject.ext.versionCode
        versionName rootProject.ext.versionName
        multiDexEnabled true
    }

    compileOptions {
        sourceCompatibility rootProject.ext.javaVersion
        sourceCompatibility rootProject.ext.javaVersion
    }

    packagingOptions {
        exclude 'LICENSE.txt'
        exclude 'META-INF/DEPENDENCIES'
        exclude 'META-INF/ASL2.0'
        exclude 'META-INF/NOTICE'
        exclude 'META-INF/LICENSE'
    }

    lintOptions {
        abortOnError rootProject.ext.abortOnLintError
        checkReleaseBuilds rootProject.ext.checkLintRelease
        quiet true
        ignoreWarnings true
        // Some libraries have issues with this.
        disable 'InvalidPackage'
        // Lint gives this warning but SDK 20 would be Android L Beta.
        disable 'OldTargetApi'
    }
    ...
}

依賴管理

那么多第三方庫(kù)的引用,在多個(gè)module里引用,修改起版本號(hào)來(lái)好辛苦,萬(wàn)一有一個(gè)漏改了(比如gson)結(jié)果導(dǎo)致了異常行為,搞不好查原因查個(gè)半天,結(jié)果摔鍵盤竟然是版本號(hào)導(dǎo)致的。

so,和上節(jié)類似,我們需要統(tǒng)一定義依賴:

def daggerVersion = "2.0.2"
def retrofitVersion = "2.0.0-beta4"
def supportVersion = "23.2.1"
def rxBindingVersion = '0.4.0'

def leakCanaryVersion = "1.3.1"
def blockCanaryVersion = '1.1.4'

project.ext {
    ...
    libSupportAppcompat = "com.android.support:appcompat-v7:${supportVersion}"
    libSupportDesign = "com.android.support:design:${supportVersion}"
    libSupportRecyclerview = "com.android.support:recyclerview-v7:${supportVersion}"
    libSupportV4 = "com.android.support:support-v4:${supportVersion}"

    libRxAndroid = "io.reactivex:rxandroid:1.1.0"
    libRxJava = "io.reactivex:rxjava:1.1.1"
    libEventBus = "org.greenrobot:eventbus:3.0.0"
    libJavaxAnnotation = "javax.annotation:jsr250-api:1.0"

    libGson = "com.google.code.gson:gson:2.4"
    libRetrofit = "com.squareup.retrofit2:retrofit:${retrofitVersion}"
    libRetrofitConverterGson = "com.squareup.retrofit2:converter-gson:${retrofitVersion}"
    libRetrofitAdapterRxJava = "com.squareup.retrofit2:adapter-rxjava:${retrofitVersion}"
    libOkHttpLoggingInterceptor = "com.squareup.okhttp3:logging-interceptor:3.0.0-RC1"

    libDagger = "com.google.dagger:dagger:${daggerVersion}"
    libDaggerCompiler = "com.google.dagger:dagger-compiler:${daggerVersion}"

    libGlide = "com.github.bumptech.glide:glide:3.7.0"

    libRxBinding = "com.jakewharton.rxbinding:rxbinding:${rxBindingVersion}"
    libRxBindingSupportV4 = "com.jakewharton.rxbinding:rxbinding-support-v4:${rxBindingVersion}"
    libRxBindingAppcompatV7 = "com.jakewharton.rxbinding:rxbinding-appcompat-v7:${rxBindingVersion}"
    libRxBindingDesign = "com.jakewharton.rxbinding:rxbinding-design:${rxBindingVersion}"
    libRxBindingRecyclerview = "com.jakewharton.rxbinding:rxbinding-recyclerview-v7:${rxBindingVersion}"

    libRealm = "io.realm:realm-android:0.87.5"

    debugDependencies = [
            leakCanary: "com.squareup.leakcanary:leakcanary-android:${leakCanaryVersion}",
            blockcanary: "com.github.moduth:blockcanary-ui:${blockCanaryVersion}",
    ]

    releaseDependencies = [
            leakCanary: "com.squareup.leakcanary:leakcanary-android-no-op:${leakCanaryVersion}",
            blockcanary: "com.github.moduth:blockcanary-no-op:${blockCanaryVersion}",
    ]
}

這里也可以根據(jù)個(gè)人喜好把版本號(hào)也全都抽出去,我個(gè)人的實(shí)踐原則是除非引用超出1處,否則還是定義在一起。

module中使用:

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    ...
    apt rootProject.ext.libDaggerCompiler
    compile rootProject.ext.libDagger
    compile rootProject.ext.libRxJava
    compile rootProject.ext.libRxAndroid
    compile rootProject.ext.libRxBinding
    compile rootProject.ext.libGlide
    provided rootProject.ext.libJavaxAnnotation
    compile rootProject.ext.libSupportAppcompat
    compile rootProject.ext.libSupportDesign
    compile rootProject.ext.libSupportRecyclerview
    compile rootProject.ext.libSupportV4
    debugCompile rootProject.ext.debugDependencies.leakCanary
    releaseCompile rootProject.ext.releaseDependencies.leakCanary
    debugCompile rootProject.ext.debugDependencies.blockCanary
    releaseCompile rootProject.ext.releaseDependencies.blockCanary
}

這里我還特地為一些debug和release compile不同包的定義了2個(gè)map,見(jiàn)leakCanary和blockCanary引用。

簽名管理

簽名是一個(gè)很敏感的東西,只要有了簽名文件和對(duì)應(yīng)的密碼信息,就能輕易反編譯修改源碼然后再簽名進(jìn)行發(fā)布,因此如何保存這些敏感信息是很重要的。

在我的個(gè)人實(shí)踐中,主要做了這么幾點(diǎn):

local.properties定義keystore信息文件路徑:

keystore.props.file=../keystore.properties

keystore.properties保存keystore信息:

store=../buildsystem/release.jks
alias=xxx
storePass=xxx
pass=xxx

buildsystem下保存了:

$ ls
ci.gradle
debug.keystore
release.jks

application module的signingConfigs:

signingConfigs {

    def Properties localProps = new Properties()
    localProps.load(new FileInputStream(file('../local.properties')))
    def Properties keyProps = new Properties()

    // 如果讀取不到'keystore.props.file'屬性,就使用debug keystore

    if (localProps['keystore.props.file']) {
        keyProps.load(new FileInputStream(file(localProps['keystore.props.file'])))
    } else {
        keyProps["store"] = '../buildsystem/debug.keystore'
        keyProps["alias"] = 'android'
        keyProps["storePass"] = 'androiddebugkey'
        keyProps["pass"] = 'android'
    }

    debug {
        storeFile file(keyProps["store"])
        keyAlias keyProps["alias"]
        storePassword keyProps["storePass"]
        keyPassword keyProps["pass"]
    }

    release {
        // release版本使用assert確保存在該屬性否則報(bào)錯(cuò),避免錯(cuò)誤打包
        assert localProps['keystore.props.file'];
        storeFile file(keyProps["store"])
        keyAlias keyProps["alias"]
        storePassword keyProps["storePass"]
        keyPassword keyProps["pass"]
    }
}

Java8支持

對(duì)Android的module

apply plugin: 'me.tatarka.retrolambda'

android {
    compileOptions {
        sourceCompatibility rootProject.ext.javaVersion
        sourceCompatibility rootProject.ext.javaVersion
    }
}

對(duì)Java的module:

sourceCompatibility = 1.8
targetCompatibility = 1.8

Split APK

詳細(xì)的可以看看Google的官方文檔Apk Splits

我的使用:

splits {
    abi {
        enable true
        reset()
        include 'armeabi', 'x86' //, 'x86', 'armeabi-v7a', 'mips'
        universalApk false
    }
}

大致來(lái)說(shuō),就是可以根據(jù)腳本的配置,將apk以abi、density進(jìn)行分包。再也不用為了縮小包的體積而專門去只留下一個(gè)arm的jni文件夾了,想怎么分怎么分,搞不定哪天就要傳一個(gè)x86的包了,而且有的模擬器也只支持x86。

當(dāng)然如果市場(chǎng)能支持這些配置,那就更好了,用戶下載apk的流量就小多了。

Module aar依賴

怎么能在使用aar依賴提升編譯速度的同時(shí),又能兼顧靈活性,隨時(shí)可以修改源碼呢?

解決方案就是module式aar依賴。

在你的library module目錄下, 打開(kāi)build/outputs/aar,是不是有aar文件(編譯過(guò)后就會(huì)生成)?把它放到module目錄下面,然后在build.gradle里面:

configurations.maybeCreate("default")
artifacts.add("default", file('lib_authorize-debug.aar'))

再把原來(lái)那些腳本給注釋了,就搞定了。是不是特別簡(jiǎn)單?如果想再使用源碼依賴,反注釋一下就好了。

總結(jié)

本篇主要講了開(kāi)發(fā)階段gradle的各種實(shí)踐,下一篇是什么暫時(shí)我也沒(méi)有想法,哈哈。

原文:http://blog.zhaiyifan.cn/2016/03/14/android-new-project-from-0-p2/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容