管理我們的 gradle 依賴

現在 android 開發中對于 gradle 也是很多技巧的,簡單的有統一管理依賴及其版本號,復雜一些的涉及到 gradle task,比如 apk 重命名,渠道包配置,buildTypes 編譯模式中配置不同的參數,如 debug 和 release 配置不同的baseUrl,最難的是自定義 gradle plugin 腳本,去執行諸如統一圖片壓縮,打包等

我對 gradle 的了解也有限,但是還是要總結一下

這里我們對 gradle 進行以下幾個方面的操作:

本文項目地址:BW_Libs

一些 gradle 的知識點,先暫時放在這里:


1. 統一管理遠程依賴

我們在根目錄創建一個 config.gradle 文件,.gradle 文件,我們可以看成 gradle 腳本。然后我們在這個 config.gradle 寫項目中需要的遠程依賴,然后在根項目的 build.gradle 中引用我們寫的 config.gradle 這個腳本就成了,大家注意寫法:

1.1 創建 config.gradle 文件
1.2 在 config.gradle 文件中書寫依賴
//第三方依賴庫和版本號管理
def versions = [:]

versions.support = "26.1.0"

versions.rxjava = "2.1.10"
versions.rx_android = "2.0.2"
versions.retrofit = "2.4.0"
versions.okhttp3 = "3.4.1"
versions.gson = "2.4.0"


ext {

    android = [
            compileSdkVersion: 26,
            buildToolsVersion: '26.0.2',
            minSdkVersion    : 19,
            targetSdkVersion : 26,
            applicationId    : 'com.bloodcrown.bw',
            versionCode      : 1,
            versionName      : '1.0',
            //            multiDexEnabled  : true
    ]

    signConfigs = [
            'storeFile'    : 'sign.jks',
            'storePassword': '123456',
            'keyAlias'     : 'sign',
            'keyPassword'  : '123456'
    ]

    java = [
            'javaVersion': JavaVersion.VERSION_1_8
    ]

    dependence = [

            // 官方
            'appcompatv7'            : "com.android.support:appcompat-v7:$versions.support",
            'supportv4'              : "com.android.support:support-v4:$versions.support",
            'design'                 : "com.android.support:design:$versions.support",
            'recyclerview'           : "com.android.support:recyclerview-v7:$versions.support",

            // rxjava2
            'rxjava'                 : "io.reactivex.rxjava2:rxjava:$versions.rxjava",
            'rxandroid'              : "io.reactivex.rxjava2:rxandroid:$versions.rx_android",

            // retrofit2
            'retrofit'               : "com.squareup.retrofit2:retrofit:$versions.retrofit",
            'gson'                   : "com.squareup.retrofit2:converter-gson:$versions.gson",
            'retrofitAdapter'        : "com.squareup.retrofit2:adapter-rxjava2:$versions.retrofit",

            // okhttp3
            'okhttp3'              : "com.squareup.okhttp3:okhttp:$versions.okhttp3",
            'http3LoggingInterceptor': "com.squareup.okhttp3:logging-interceptor:$versions.okhttp3",

    ]
}
1.3 根項目 build.gradle 引用 config.gradle 腳本
// Top-level build file where you can add configuration options common to all sub-projects/modules.

// 引入 config.gradle  腳本
apply from: this.file( "config.gradle" )


//引入文件
//apply from: this.file('common.gradle')
buildscript {
    ext.kotlin_version = '1.2.71'
    ext.recyclerview_version = '26.1.0'
    ext.gradle_version = '3.0.1'

    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath 'me.tatarka:gradle-retrolambda:3.2.5'
        classpath "com.android.tools.build:gradle:$gradle_version"
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        google()
        jcenter()
        maven { url 'http://repo1.maven.org/maven2' }
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}
1.4 使用 config.gradle 腳本中的依賴


apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'

//apply from: rootProject.file( "config.gradle" )

android {

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

    defaultConfig {

        applicationId rootProject.ext.android.applicationId
        minSdkVersion rootProject.ext.android.minSdkVersion
        targetSdkVersion rootProject.ext.android.targetSdkVersion
        versionCode rootProject.ext.android.versionCode
        versionName rootProject.ext.android.versionName

        vectorDrawables.useSupportLibrary = true
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    dataBinding {
        enabled = true
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')

    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.1'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'

    implementation rootProject.ext.dependence.design
    implementation rootProject.ext.dependence.appcompatv7
    implementation rootProject.ext.dependence.recyclerview

    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
    implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
    kapt "com.android.databinding:compiler:$rootProject.ext.gradle_version"
    implementation 'com.android.support.constraint:constraint-layout:1.1.2'
    implementation project(':basecomponents')

    // retrofit 依賴
    implementation rootProject.ext.dependence.rxandroid
    implementation rootProject.ext.dependence.rxjava
    implementation rootProject.ext.dependence.retrofit
    implementation rootProject.ext.dependence.gson
    implementation rootProject.ext.dependence.retrofitAdapter
    implementation rootProject.ext.dependence.http3LoggingInterceptor
    implementation rootProject.ext.dependence.okhttp3
}

2. 提取所有 module gradle 公共配置項 common.gradle

上面我們使用 config.gradle 記錄統一從 module 抽取出來的遠程依賴,做成公共的一份再由 module 各自選取其中的依賴,然后我們在 config.gradle 中改遠程依賴的版本號就可以在所有的 module 都生效了,這就是 java 中抽象封裝的思想,難度是 gradle 語言上手不友好,自動提示出來的不是我們要的, 很難寫

那么現在我們繼續深入發揮這個 抽象封裝 的思路,每個 module 中都有相同的配置項,我們把這個抽取出來,還是統一寫到 common.gradle 中,然后每個 module 都依賴這個 common.gradle 即可,和 config.gradle 區別是,config.gradle 根目錄 .gradle 引入就行了, common.gradle 需要所有的 module 都引用一份

common.gradle 中的依賴和配置也是要引用 config.gradle 的

2.1 創建 config.gradle 文件
2.2 書寫 common.gradle
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'

//kapt {
//    arguments {
//        arg("moduleName", project.getName())
//    }
//}

android {

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

    defaultConfig {

        minSdkVersion rootProject.ext.android.minSdkVersion
        targetSdkVersion rootProject.ext.android.targetSdkVersion

        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

        vectorDrawables.useSupportLibrary = true

//        multiDexEnabled true

        ndk {
            abiFilters 'armeabi', 'x86'
        }
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    dataBinding {
        enabled = true
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {

    implementation fileTree(dir: 'libs', include: ['*.jar'])

    testImplementation rootProject.ext.dependence.junit
    androidTestImplementation rootProject.ext.dependence.runner
    androidTestImplementation rootProject.ext.dependence.espresso
    implementation rootProject.ext.dependence.multidex

    implementation rootProject.ext.dependence.kotlinStdlibJdk8
    implementation rootProject.ext.dependence.kotlinReflect
    kapt rootProject.ext.dependence.databinding

}
repositories {
    mavenCentral()
}
2.3 module 引入 common.gradle 依賴

app module:

apply plugin: 'com.android.application'

apply from:rootProject.file('common.gradle')

android {

    defaultConfig {

        applicationId rootProject.ext.android.applicationId
        versionCode rootProject.ext.android.versionCode
        versionName rootProject.ext.android.versionName
    }

    signingConfigs {

        //release版的簽名配置信息
        release {
            storeFile file(rootProject.ext.signConfigs.storeFile)
            storePassword rootProject.ext.signConfigs.storePassword
            keyAlias rootProject.ext.signConfigs.keyAlias
            keyPassword rootProject.ext.signConfigs.keyPassword
        }
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {

    implementation project(':basecomponents')
    implementation project(':baselib')
    implementation project(':common_repositroy')

    implementation rootProject.ext.dependence.design
    implementation rootProject.ext.dependence.appcompatv7
    implementation rootProject.ext.dependence.recyclerview
    implementation rootProject.ext.dependence.constraintLayout

    // retrofit 依賴
    implementation rootProject.ext.dependence.rxandroid
    implementation rootProject.ext.dependence.rxjava
    implementation rootProject.ext.dependence.retrofit
    implementation rootProject.ext.dependence.gson
    implementation rootProject.ext.dependence.retrofitAdapter
    implementation rootProject.ext.dependence.http3LoggingInterceptor
    implementation rootProject.ext.dependence.okhttp3
}

其他 module:

apply plugin: 'com.android.library'
apply from:rootProject.file('common.gradle')

android {

    defaultConfig {
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

}

dependencies {

    implementation project(':baselib')

    implementation rootProject.ext.dependence.appcompatv7

    // retrofit 依賴
    implementation rootProject.ext.dependence.rxandroid
    implementation rootProject.ext.dependence.rxjava
    implementation rootProject.ext.dependence.retrofit
    implementation rootProject.ext.dependence.gson
    implementation rootProject.ext.dependence.retrofitAdapter
    implementation rootProject.ext.dependence.http3LoggingInterceptor
    implementation rootProject.ext.dependence.okhttp3
}

這樣每個 module 只關心自己的需要的特殊依賴,配置就行,app moule 中還是有很多配置需要寫的,這些配置涉及 app 打包等,所以不適合寫進公共配置


gradle 補充

其實我們的 app 若不是很復雜的話或是大家嫌上面麻煩的話,還有一種更簡單的寫法,當然不是那么正式了

app 構建時在根目錄提供了一個 gradle.properties 文件,這個 gradle.properties 就是提供書寫 gradle 參數的地方,使用起來也很簡單,直接調名字即可

apply plugin: 'com.android.library'

android {
    lintOptions {
        abortOnError false
    }

    compileSdkVersion Integer.parseInt(ANDROID_COMPILE_SDK_VERSION)
    buildToolsVersion project.ANDROID_BUILD_TOOLS_VERSION

    defaultConfig {
        minSdkVersion Integer.parseInt(ANDROID_MIN_SDK_VERSION)
        targetSdkVersion Integer.parseInt(ANDROID_BUILD_TARGET_SDK_VERSION)
        versionCode Integer.parseInt(APP_VERSION_CODE)
        versionName project.APP_VERSION_NAME
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_7
        targetCompatibility JavaVersion.VERSION_1_7
    }
}

ext {
    supportLibraryVersion = project.ANDROID_SUPPORT_LIBRARY_VERSION
}

dependencies {
    testImplementation 'junit:junit:4.12'
    implementation "com.android.support:appcompat-v7:${supportLibraryVersion}"
    implementation "com.android.support:design:${supportLibraryVersion}"
}

// Place it at the end of the file
apply from: 'install_lib.gradle'
apply from: 'bintray_lib.gradle'

3. 修改資源文件目錄

這個需求在多渠道打包或是插件化時常用,比如不同渠道包 icon 圖標不同,切換子 module 類型

看下面的例子

3.1 切換 module 類型
android {
    sourceSets {
        main {
            if(isDebug.toBoolean()) {
                manifest.srcFile 'src/debug/AndroidManifest.xml'
            } else {
                manifest.srcFile 'src/release/AndroidManifest.xml'
            }
        }
    }
}
3.2 修改 java 文件路徑
android {
    // ...
    sourceSets {
        debug {
            java.srcDirs = ['src/main/java', 'src/debug/java']
        }
        release {
            java.srcDirs = ['src/main/java', 'src/release/java']
        }
    }
}
3.3 修改 module 依賴

和 3.2 一樣,我們在不筒的 buildType 編譯版本時,可以修改 module 依賴

dependencies {
    // ...
    debugImplementation project(':basecomponents')
    releaseImplementation project(':basecomponents')
}

修改資源路徑時請慎重,因為非常容易出問題,而且很難搞~


4. 給 module 添加資源前綴 resourcePrefix

app 不管有多少 module ,最后都是整合到一起打成一個 dex 的,除非 dex 太大,報 65535了,才會拆分多個 dex 。所以 module 中的資源文件都會何必在一起的,這樣難免會出現資源重名的問題,這可是會報錯的,怎么辦?

google 提供了 resourcePrefix 資源前綴

andorid{
    ...

    buildTypes{
        ...
    }

    resourcePrefix "moudle_prefix"
}

但是這樣也不是就高枕無憂了,resourcePrefix 可以給 res 文件夾下的文件加前綴,但是圖片資源就不行了,圖片我們還是需要在命名時自己添加前綴


5. 去除重復依賴

這里我們要解決的是,我們引入的遠程依賴中依賴的組件和我們本地遠程依賴存在版本號的差異,這樣 as 在編譯的時候很多時候報錯

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile("com.jude:easyrecyclerview:$rootProject.easyRecyclerVersion") {
        exlude module: 'support-v4'//根據組件名排除
        exlude group: 'android.support.v4'//根據包名排除
    }
}

5.1 arr 打包不打 jar 進來

在打包 libs module realese版本 的 arr 時,是包含libs目錄下的文件,這時候你引入這個aar,可能會和你現有引入的jar文件沖突,著要求我們在打包 aar 的時候設置不引入libs文件,做法是使用 compile 依賴本地 jar 文件

dependencies {

// 去掉默認 libs 文件夾依賴
// implementation fileTree(include: ['*.jar'], dir: 'libs')

// 轉而使用 compile files + jar 的方式提供依賴
compile files('libs/commons-lang-2.6.jar')
compile files('libs/simple-xml-2.7.jar')
compile files('libs/agnes_tracker-0.1.0.jar')
}

6. 修改 module 路徑

我們在開發時總是愿意把相同類型的類放在一起,這點放到 module 身上也是一樣的,比哦如我希望業務組件類型的 module 都在一個文件夾下,這樣好看好找不是

module 的配置是在 根項目 的 setting.gradle 中,那么我們去 setting.gradle 里面改好了

通常的 module 路徑配置我們這么寫

include ':app', ':basecomponents', ':baselib', ':common_repositroy'

但是我們可以自己在 根項目 里新建一個文件夾,然后把 module 放進去,那么我們這樣寫就行

project(':basecomponents').projectDir = new File( 'components/basecomponents' )
project(':common_repositroy').projectDir = new File( 'components/common_repositroy' )

7. gradle 修改 manifest 配置文件參數

在 manifest 配置文件我們可以定義 <meta-data> 參數,這個 <meta-data> 參數在 gradle 文件中可以修改的,這也是多渠道打包的基礎

<meta-data>

  <meta-data
            android:name="UMENG_CHANNEL"
            android:value="${UMENG_CHANNEL_VALUE}"/>

gradle 修改值

manifestPlaceholders = [UMENG_CHANNEL_VALUE: "yingyongbao"]

大家在集成友盟統計時,就是這么干的


8. gradle 中創建參數

我們在 gradle 聲明一個參數,然后根據不同的環境,修改為不同數據,這個最典型的應用就是 baseUrl 的處理了,debug 和 release 環境下 baseUrl 是不同的

gradle 聲明參數有2種寫法:

// 注意字符串單引號里面要套雙引號
buildConfigField 'String', 'app_name', '"HHHHHH"'

// 在 values 中聲明參數
resValue "color", "flav_color", "#00ffff"

java 代碼獲取參數

Log.d("test", BuildConfig.app_name);

tx_info.setTextColor(getResources().getColor(R.color.flav_color));

這里我們來看看 debug 和 release 環境下修改 baseUrl

    buildTypes {

        debug{
            buildConfigField( 'String','baseUrl','"baseUrl_debug"' )
        }
        release {
            buildConfigField( 'String','baseUrl','"baseUrl_release"' )
        }
    }
        btn_toast.setOnClickListener({
            ToastComponent.instance.show("baseUrl = " + BuildConfig.baseUrl);
        })

經過測試的確是可以改變 baseUrl 參數的


9. NDK 配置

1. 配置 SO 支持庫類型
android {

    defaultConfig {
        ndk {

            // APP的build.gradle設置支持的SO庫架構
            abiFilters 'armeabi', 'armeabi-v7a', 'x86'
        }
    }
}

這個 so 庫配置聲明了我們支持哪些 CPU 架構,一般現在我們除了 ARM CPU 架構外都不考慮了,這個配置我們寫在 module 公共配置項 common.gradle 里面

2. 配置 SO 支持庫位置

android{   
   sourceSets {
        main {
            jniLibs.srcDirs = ['libs']
        }
}

這樣我們就可以把 .jar 和 .so 放在一起了


10. buildType 不同編譯類型種我們一般都配置什么

基本上都是配 混淆,簽名,各種參數,AndroidManifest 的 mate_data,其他的看字個特殊需求了

// 簽名配置
signingConfigs {
    debug {
        storeFile file("../debug.jks")
        storePassword "123456"
        keyAlias "debug"
        keyPassword "123456"
    }
    release {
        storeFile file("../release.jks")
        storePassword "123456"
        keyAlias "release"
        keyPassword "123456"
    }
}

// 編譯類型中我們通暢的配置項
buildTypes {
    debug {

        // 混淆配置
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

        // 簽名配置
        signingConfig signingConfigs.debu

        // 各種參數配置,比如 URL
        buildConfigField "String", "URL_HOST","\"https://XXXX.XXXX.XXXX/""
        buildConfigField "String", "QQ_APPID", "\"11111111111\""
        buildConfigField "String", "QQ_APPSECRET", "\"XXXXXXXXXXXXXXXX\""
        buildConfigField "Boolean", "DEBUG_TAG", "true"

        // AndroidManifest 的各種 mate_data
        manifestPlaceholders = [BAIDU_KEY_VAULE        : "fffffffffffffffffffff"]
        manifestPlaceholders = [UMENG_CHANNEL_VALUE    : "xxxxxxxxx"]
    }

    release {

        minifyEnabled true //開啟混淆編譯
        shrinkResources true //移除無用資源
        zipAlignEnabled true //zipalign優化
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

        signingConfig signingConfigs.release

        buildConfigField "String", "URL_HOST","\"https://XXXX.XXXX.XXXX/""
        buildConfigField "String", "QQ_APPID", "\"11111111111\""
        buildConfigField "String", "QQ_APPSECRET", "\"XXXXXXXXXXXXXXXX\""
        buildConfigField "Boolean", "DEBUG_TAG", "false"

        manifestPlaceholders = [BAIDU_KEY_VAULE        : "fffffffffffffffffffff"]
        manifestPlaceholders = [UMENG_CHANNEL_VALUE    : "xxxxxxxxx"]
    }
}

11. 自定義 apk 名字

android {
    // 自定義輸出apk名字
    applicationVariants.all {
        variant ->
            variant.outputs.all { output ->
                outputFileName = new File("app_" +
                        buildType.name +
                        "_v" + defaultConfig.versionName + "_" +
                        new Date().format("yyyy-MM-dd")+ ".apk")
            }
    }
}

跟著上面寫就行,grooy 語言兼容 java 語法,上面的寫法基本算是固定的



12. 多渠道打包

多渠道打包 gradle 代碼不難,和 buildType 一個思路,根據不同的渠道改相應的參數或是資源

比如友盟統計:

/*配置渠道*/
productFlavors {
    wandoujia{
        manifestPlaceholders = [UMENG_CHANNEL_VALUE: "wandoujia"]
    }
    yingyongbao{
        manifestPlaceholders = [UMENG_CHANNEL_VALUE: "yingyongbao"]
    }
   huawei{
        manifestPlaceholders = [UMENG_CHANNEL_VALUE: "huawei"]
    }
  ........
}

    //自動替換清單文件中的渠道號
    productFlavors.all {
        flavor -> flavor.manifestPlaceholders = [UMENG_CHANNEL_VALUE: name]
    }

這樣打渠道包的缺點:

  • 每一個渠道包需要release一次
  • 我們上傳應用市場的時候都需要加固,加固后渠道信息會丟失,所以必須加固后再打渠道包

使用360加固時,支持多渠道打包,這樣使用比較方便


注意:友盟統計的渠道號不能全是數字

還有一種是使用三方開源的打包工具,比如美團開源的打包工具:walle


13. 自動維護版本發布文檔 gradle 腳本

這個腳本,我是看這篇文章找到的,很贊

gradle 腳本:releaseinfo.gradle

import groovy.xml.MarkupBuilder

/**
 * 描述:版本發布文檔自動維護腳本
 * 流程描述:
 *           1、將版本相關信息解析出來
 *           2、將解析出的數據生成xml格式數據
 *           3、寫入到已有的文檔數據中
 **/
ext {
    versionName = rootProject.ext.android.versionName
    versionCode = rootProject.ext.android.versionCode
    versionInfo = 'App的第1個版本,上線了一些最基礎核心的功能,主要是要通過審核'
    destFile = file('releasesInfo.xml')//指定輸出文件
    if (destFile != null && !destFile.exists()) {
        destFile.createNewFile()
    }
}
//掛在到應用構建的過程中
this.project.afterEvaluate { project ->
    def buildTask = project.tasks.getByName('assembleRelease')
    if (buildTask != null) {
        buildTask.doLast {//assembleRelease 之后執行
            releaseInfoTask.execute()
        }
    }
}
//創建一個Task,并指定輸入輸出
task releaseInfoTask {
    inputs.property('versionCode', this.versionCode)
    inputs.property('versionName', this.versionName)
    inputs.property('versionInfo', this.versionInfo)
    outputs.file this.destFile
    doLast {
        //將輸入的內容寫入到輸出文件中去
        def data = inputs.getProperties()
        File file = outputs.getFiles().getSingleFile()
        def versionMsg = new VersionMsg(data)
        //將實體對象寫入到xml文件中
        def sw = new StringWriter()
        def xmlBuilder = new MarkupBuilder(sw)
        if (file.text != null && file.text.size() <= 0) {
            //沒有內容
            xmlBuilder.releases {
                release {
                    versionCode(versionMsg.versionCode)
                    versionName(versionMsg.versionName)
                    versionInfo(versionMsg.versionInfo)
                }
            }
            //直接寫入
            file.withWriter { writer ->
                writer.append("<?xml version=\"1.0\" encoding=\"GBK\"?>" + '\r\n')
                writer.append(sw.toString())
            }
        } else {//有內容判斷版本是否改變
            def releases = new XmlParser().parse(file)
            def codeName = releases.release[-1].versionName.text()
            if (codeName != versionMsg.versionName) {//新的版本信息
                xmlBuilder.release {
                    versionCode(versionMsg.versionCode)
                    versionName(versionMsg.versionName)
                    versionInfo(versionMsg.versionInfo)
                }
                //插入到最后一行前面
                def lines = file.readLines()
                def lengths = lines.size() - 1
                file.withWriter { writer ->
                    lines.eachWithIndex { line, index ->
                        if (index != lengths) {
                            writer.append(line + '\r\n')
                        } else if (index == lengths) {
                            writer.append('\r\n' + sw.toString() + '\r\n')
                            writer.append(lines.get(lengths))
                        }
                    }
                }
            }
        }
    }
}
//信息實體類
class VersionMsg {
    String versionCode
    String versionName
    String versionInfo
}

app module 殼工程依賴這個腳本就行啦

apply from: rootProject.file('releaseinfo.gradle')

然后我們在打 release 包之后就在 app 項目下自動生成 releaseInfo.xml文件


<?xml version="1.0" encoding="GBK"?>
<releases>
  <release>
    <versionCode>1</versionCode>
    <versionName>1.0</versionName>
    <versionInfo>App的第1個版本,上線了一些最基礎核心的功能,。。。。。。</versionInfo>
  </release>
</releases>

14. gradle 標準組件化設置

組件化中要求我們的 業務module 可以在 library 和 application 中任意切換,測試時我們可以把 業務module 單獨打成一個 apk 去運行,插件化時我們也是把 業務module 打成 apk 下發到殼工程 APP

  1. 工程根目錄下的 gradle.properties 中配置業務組件 Library/Application 切換的開關
isRunLogin = false  //login組件
isRunHome = false //home組件
isRunNews = false  //news組件

// 切換 application/Library 
if (isRunHome.toBoolean()){
    apply plugin: 'com.android.application'
}else{
    apply plugin: 'com.android.library'
}
}

注意:其實每個 modul 里面自己也可以放一個 gradle.properties,在自己 module 的 build.gradle 中都可以讀出來

  1. 不同 buildType 設置不同的資源,文件路徑,包括使用不同包下的class 和忽略一些不需要的包
android {
    .......

sourceSets {
        main {
            if (isModule.toBoolean()) {
                // 組件化編譯時為app,在對應的AndroidManifest文件中需要寫ndroid.intent.action.MAIN入口Activity
                manifest.srcFile 'src/main/module/AndroidManifest.xml'
                // 多級 java 目錄
                java.srcDirs 'src/main/module/debug', 'src/main/java'
            } else {
                manifest.srcFile 'src/main/AndroidManifest.xml'
                //集成開發模式下排除debug文件夾中的所有Java文件
                java {
                    // 可以排除文件夾 - debug文件夾中放的是Application類,非組件化時不用有此類
                    exclude 'debug/**'
                    // 也可以重新指定文件夾 - 只保留原有的java目錄
                    java.srcDirs 'src/main/java'
                }
            }
        }
    }
  1. 業務 module 單獨打成 apk 時,我們要設置進程 ID 的,并且主工程此時是不能依賴編譯模式是 application 的子 module 的



代碼隔離

主要針對 app 殼工程來說的,殼工程會依賴所有的 module,但是在組件化中我們一樣會要求 app 這個 module 不能直接使用其他業務 module 的 api,雖說我們可以用代碼規范來嚴格要求,但是保不住哪里我們自己沒注意就用了呢,所以就需要代碼隔離了,在編碼時不依賴,編譯時依賴,這里我們就需要借助 runtimeOnly 了



多渠道動態配置 ApplicationId,App名字,AppLogo

這是別人的方案:http://www.lxweimin.com/p/f3b3e947ae04

核心思路是在 java/main 之外創建和 main 同級別的目錄存放資源,然后在配置文件里使用動態參數,在 gradle 的多渠道中賦值


1

2
3

參考資料:


最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容