android 项目 gradle 统一版本管理

目前的android开发为了减少编译时间,开发效率,大多都采用模块化,组件化的开发方式。采用这种方式不可避免的将会用到多个Library。 那么当我们协同开发时,如何处理每个人的版本统一呢?

当你的项目中 module 的数量超过一个甚至越来越多的时候,对 Gradle 依赖进行统一管理就变得重要起来,因为你不会想在升级一个三方依赖的版本后发现冲突,然后一个个打开各个 module 的 build.gradle 文件,找到你升级的那个依赖引用,重复的进行版本修改;

因此我们有了初步的优化方案:

  • 在项目根目录下创建 config.gradle 文件,在其中按照以下格式添加相关配置;
ext {


    /**
     * module开关统一申明在此处
     * true: 表示作为一个模块
     * false: 表示作为独立程序,可单独运行
     */
    isModule_a = true
    isModule_b = true

//    isModule_Location = false
//    isModule_Login = false
//    isModule_Main = false
//    isModule_Personal = false
//    isModule_ProductDetail = false
//    isModule_ShoppingCar = false

    /**
     * 版本信息统一管理
     */
    android = [
            compileSdkVersion: 31,
            buildToolsVersion: "30.0.3",
            applicationId    : "com.XXXX.XXXX",
            minSdkVersion    : 24,
            targetSdkVersion : 31,//27以上的版本http请求 权限不允许
            versionCode      : 1,
            versionName      : "1.0.0"
    ]
    dependencies = [
            //basic
            "appcompat"             : 'androidx.appcompat:appcompat:1.4.1',
            "material"              : 'com.google.android.material:material:1.5.0',
            "constraintlayout"      : 'androidx.constraintlayout:constraintlayout:2.1.3',
            "navigation-fragment"   : 'androidx.navigation:navigation-fragment:2.4.1',
            "navigation-ui"         : 'androidx.navigation:navigation-ui:2.4.1',


            //Rxjava
            "rxjava"                : "io.reactivex.rxjava2:rxjava:2.1.6",
            "rxandroid"             : "io.reactivex.rxjava2:rxandroid:2.0.1",
            "rxrelay"               : "com.jakewharton.rxrelay2:rxrelay:2.0.0",

            /*Rx生命周期管理*/
            "rxlifecycle"           : "com.trello.rxlifecycle2:rxlifecycle:2.2.0",
            "rxlifecycle-components": "com.trello.rxlifecycle2:rxlifecycle-components:2.2.0",


            //Retrofit
            "retrofit"              : "com.squareup.retrofit2:retrofit:2.4.0",
            "retrofit-gson"         : "com.squareup.retrofit2:converter-gson:2.4.0",
            "retrofit-adapter"      : "com.squareup.retrofit2:adapter-rxjava2:2.4.0",
            "okhttp-log-interceptor": "com.squareup.okhttp3:logging-interceptor:3.10.0",
            "okhttp3"               : "com.squareup.okhttp3:okhttp:3.10.0",
            "gson"                  : "com.google.code.gson:gson:2.8.2",
            "logger"                : "com.orhanobut:logger:2.1.1",

            //butterknife
            "butterknife"           : "com.jakewharton:butterknife:10.1.0",
            "butterknife-anno"      : "com.jakewharton:butterknife-compiler:10.1.0",

            /*eventBus*/
            "eventBus"              : "org.greenrobot:eventbus:3.1.1",

            //room
            "room"                  : "androidx.room:room-runtime:2.2.5",
            "room-anno"             : "androidx.room:room-compiler:2.2.5",
            "room-rxjava2"          : "androidx.room:room-rxjava2:2.2.5", // 如果需要用到 rxjava
            "room-guava"            : "androidx.room:room-guava:2.2.5",// 如果需要用到 guava
            "room-testing"          : "androidx.room:room-testing:2.2.5",//需要用到相关测试工具的话

            //cameraX
            "camerax-core"          : "androidx.camera:camera-camera2:1.0.0-beta06",//CameraX 核心库
            "camerax-lifecycle"     : "androidx.camera:camera-lifecycle:1.0.0-beta06",// CameraX 生命周期
            "camerax-view"          : "androidx.camera:camera-view:1.0.0-alpha10", //CameraX view 集合,比如 cameraview,preview等

            //Glide  4.11.0 才适配AndroidX
            "Glide"                 : "com.github.bumptech.glide:glide:4.11.0",
            "Glide-anno"            : "com.github.bumptech.glide:compiler:4.11.0",

            //腾讯buggly
            "TecentBugly"           : "com.tencent.bugly:crashreport:latest.release",
            "TecentBugly-native"    : "com.tencent.bugly:nativecrashreport:latest.release",

            // 屏幕适配集成
            "Screen-Adapter"        : "me.jessyan:autosize:1.2.1",

            //组件化 Arouter
            "Arouter"               : "com.alibaba:arouter-api:1.2.2",
            "Arouter-anno"          : "com.alibaba:arouter-compiler:1.1.3"

    ]

    avcProtocol = [
            "innerNet": "ws://",//ws
            "extraNet": "wss://"
    ]

    url = [

//            "debug"  : "https://XXXXX.XXXXX.cn",//


//              "debug"  : "http://192.168.71.126",//

    ]

    port = [
//           // "debug_port"   : 53073  ,//avc

    ]

    filefolder = [
            "release_root_folder": "",
            "debug_root_folder"  : "_debug"
    ]

}
  • 在项目根目录下的 build.gradle 文件顶部添加 apply from: "config.gradle"

gradle 7.0 之前

// Top-level build file where you can add configuration options common to all sub-projects/modules.
println  "----- RootGradle Start -----"

apply from: "${rootProject.getRootDir()}/config.gradle"

println  "RootGradle ext path--->"+"${rootProject.getRootDir()}/config.gradle"

buildscript {
    repositories {
        google()
        mavenCentral()
    }
    dependencies {
        classpath "com.android.tools.build:gradle:4.1.0"

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

task clean(type: Delete) {
    delete rootProject.buildDir
}

gradle 7.0之后

// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
    id 'com.android.application' version '7.2.2' apply false
    id 'com.android.library' version '7.2.2' apply false
    id 'org.jetbrains.kotlin.android' version '1.6.10' apply false
}
apply from: this.rootProject.file('config.gradle')

task clean(type: Delete) {
    delete rootProject.buildDir
}

  • 在各个 module 的 build.gradle 中就可以通过 rootProject 来引用对应的依赖及参数了;

app 的build.gradle

plugins {
    id 'com.android.application'
}

println "----- app Start -----"

android {
    def versionConfig = rootProject.extensions.getByName("ext").android
    println "---app versionConfig is:" + versionConfig

    namespace 'com.demo.agreebankmvvm'
    compileSdk versionConfig.compileSdkVersion
    buildToolsVersion versionConfig.buildToolsVersion

    defaultConfig {
        applicationId "com.demo.agreebankmvvm"

        minSdk      versionConfig.minSdkVersion
        targetSdk   versionConfig.targetSdkVersion
        versionCode rootProject.ext.android["versionCode"]
        versionName rootProject.ext.android["versionName"]

        //版本名后面添加一句话,意思就是flavor dimension 它的维度就是该版本号,这样维度就是都是统一的了
        flavorDimensions "channel"

        //指定room.schemaLocation生成的文件路径
        javaCompileOptions {
            annotationProcessorOptions {
                arguments = ["room.schemaLocation": "$projectDir/schemas".toString()]
            }
        }

        //arouter
        javaCompileOptions {
            annotationProcessorOptions {
                arguments = [ moduleName : project.getName() ]
            }
        }
    }

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

    signingConfigs {
        release {//发布版本的签名配置
            storeFile file(rootProject.RELEASE_KEYSTORE_FILE)
            keyAlias rootProject.RELEASE_KEY_ALIAS
            storePassword rootProject.RELEASE_KEYSTORE_PWD
            keyPassword rootProject.RELEASE_KEY_PWD
        }
        debug {//调试版本的签名配置
            storeFile file(rootProject.DEBUG_KEYSTORE_FILE)
            keyAlias rootProject.DEBUG_KEY_ALIAS
            storePassword rootProject.DEBUG_KEYSTORE_PWD
            keyPassword rootProject.DEBUG_KEY_PWD
        }
    }

    buildTypes {
        debug {
            File file = new File("${rootProject.getRootDir()}/jks/debugBank.jks")
            println "---debug signkey file is:" + file.exists()
            signingConfig signingConfigs.debug
            buildConfigField('String', 'PROJECT_ROOTFILE', "\"${filefolder["debug_root_folder"]}\"") //debug根文件夹名称
            buildConfigField('String', 'SERVER_URL', "\"${url["debug"]}\"")//配置debug的服务器地址
            buildConfigField('int', 'MESSAGE_URL_PORT', "${port["debug_port"]}") //配置debug模式下的服务器端口
            buildConfigField('String', 'avc_innerprotocol', "\"${avcProtocol["innerNet"]}\"")  //配置debug模式下的协议内网(avc的初始化用)
            buildConfigField('String', 'avc_extraprotocol', "\"${avcProtocol["extraNet"]}\"") //配置debug模式下的协议外网(avc的初始化用)
        }
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
            File file = new File("${rootProject.getRootDir()}/jks/releaseBank.jks")
            println "---release signkey file is:" + file.exists()
            signingConfig signingConfigs.release
            buildConfigField('String', 'PROJECT_ROOTFILE', "\"${filefolder["release_root_folder"]}\"") //release根文件夹名称
            buildConfigField('String', 'SERVER_URL', "\"${url["release"]}\"")//配置release模式下的服务器地址
            buildConfigField('int', 'MESSAGE_URL_PORT', "${port["release_port"]}") //配置release模式下的服务器的端口
            buildConfigField('String', 'avc_extraprotocol', "\"${avcProtocol["extraNet"]}\"") //配置 release模式下的协议(avc的初始化用)
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    //多渠道打包
    productFlavors {

        //juphone版本
        juPhonePHONE {
            buildConfigField('int', 'videoType', '0')
            buildConfigField('String', 'machineType',  "\"phone\"" )
            buildConfigField('String', 'channelType',  "\"C002\"" )
            applicationId "com.agree.bank.client_phone.phone"
            applicationIdSuffix ".juPhone"
            //替换清单文件中的标签
            manifestPlaceholders = [
                    APP_ICON: "@mipmap/debug",
                    APP_NAME: "phone-juPhone-BK",
            ]
            //versionName
            versionName "1.0.0"
            //versionCode
            versionCode 1
        }

        juPhonePAD {
            buildConfigField('int', 'videoType', '0')
            buildConfigField('String', 'machineType', "\"pad\"")
            buildConfigField('String', 'channelType',  "\"C003\"" )
            applicationId "com.agree.bank.client_phone.pad"
            applicationIdSuffix ".juPhone"
            //替换清单文件中的标签
            manifestPlaceholders = [
                    APP_ICON: "@mipmap/debug",
                    APP_NAME: "pad-juPhone-BK",
            ]
            //versionName
            versionName "1.0.0"
            //versionCode
            versionCode 1
        }
        //avc版本
        AVCPHONE {
            buildConfigField('int', 'videoType', '1')
            buildConfigField('String', 'machineType',   "\"phone\"" )
            buildConfigField('String', 'channelType',  "\"C002\"" )
            applicationId "com.agree.bank.client_phone.phone"
            applicationIdSuffix ".AVC"
            //替换清单文件中的标签
            manifestPlaceholders = [
                    APP_ICON: "@mipmap/ic_launcher_round",
                    APP_NAME: "phone-AVC-BK",
            ]
            //versionName
            versionName "1.0.0"
            //versionCode
            versionCode 1
        }

        AVCPAD {
            buildConfigField('int', 'videoType', '1')
            buildConfigField('String', 'machineType', "\"pad\"")
            buildConfigField('String', 'channelType',  "\"C003\"" )
            applicationId "com.agree.bank.client_phone.pad"
            applicationIdSuffix ".AVC"
            //替换清单文件中的标签
            manifestPlaceholders = [
                    APP_ICON: "@mipmap/ic_launcher_round",
                    APP_NAME: "pad-AVC-BK",
            ]
            //versionName
            versionName "1.0.0"
            //versionCode
            versionCode 1
        }

        //trtc版本
        TrtcPHONE {
            buildConfigField('int', 'videoType', '2')
            buildConfigField('String', 'machineType',   "\"phone\"" )
            buildConfigField('String', 'channelType',  "\"C002\"" )
            applicationId "com.agree.bank.client_phone.phone"
            applicationIdSuffix ".trtc"
            //替换清单文件中的标签
            manifestPlaceholders = [
                    APP_ICON: "@mipmap/ic_launcher_round",
                    APP_NAME: "phone-TRTC-BK",
            ]
            //versionName
            versionName "1.0.0"
            //versionCode
            versionCode 1
        }

        TrtcPAD {
            buildConfigField('int', 'videoType', '2')
            buildConfigField('String', 'machineType', "\"pad\"")
            buildConfigField('String', 'channelType',  "\"C003\"" )
            applicationId "com.agree.bank.client_phone.pad"
            applicationIdSuffix ".trtc"
            //替换清单文件中的标签
            manifestPlaceholders = [
                    APP_ICON: "@mipmap/ic_launcher_round",
                    APP_NAME: "pad-TRTC-BK",
            ]
            //versionName
            versionName "1.0.0"
            //versionCode
            versionCode 1
        }

    }

    //打包重命名
    android.applicationVariants.all {
        variant ->
            variant.outputs.all {
                output -> output.outputFileName = "app" + "-PackTime" + new Date().format("yyyy-MM-dd", TimeZone.getTimeZone("UTC")) +"--" +buildType.name+ ".apk"
            }
    }

    //databinding
    buildFeatures.dataBinding = true

}

dependencies {

    // >基础依赖 - 其他模块需要可以单独依赖
    implementation project(':librarys:lib_basic')
    //ui_libary
    implementation project(':librarys:lib_ui')
    //pop_libary
    implementation project(':librarys:lib_pop')
    //net_libary
    implementation project(':librarys:lib_net')

    // 引入各个模块
    if (rootProject.ext.isModule_a) {
        implementation project(path: ':modules:module_a')
    }
    if (rootProject.ext.isModule_b) {
        implementation project(path: ':modules:module_b')
    }

    //retrofit
    implementation rootProject.ext.dependencies["retrofit"]
    implementation rootProject.ext.dependencies["retrofit-gson"]
    implementation rootProject.ext.dependencies["retrofit-adapter"]

    //okhttp
    implementation rootProject.ext.dependencies["okhttp-log-interceptor"]
    implementation rootProject.ext.dependencies["okhttp3"]

    // gson
    implementation rootProject.ext.dependencies["gson"]

    //room
    implementation rootProject.ext.dependencies["room"]
    annotationProcessor rootProject.ext.dependencies["room-anno"]
    implementation rootProject.ext.dependencies["room-rxjava2"]

    //arouter
    implementation rootProject.ext.dependencies["Arouter"]
    annotationProcessor rootProject.ext.dependencies["Arouter-anno"]

}

App 的manifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <uses-permission android:name="android.permission.INTERNET"/>

    <application
        android:name="com.demo.agreebankmvvm.App"
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:networkSecurityConfig="@xml/network_security_config"
        android:supportsRtl="true"
        android:theme="@style/Theme.AgreeBankMVVM"
        tools:targetApi="31">

        <activity android:name=".view.activity.TestBVMActivity"/>
        <activity android:name=".view.activity.TestBindActivity"/>
        <activity
            android:name=".view.activity.MainActivity"
            android:exported="true"
            android:label="@string/app_name"
            android:theme="@style/Theme.AgreeBankMVVM.NoActionBar">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>

            <meta-data
                android:name="android.app.lib_name"
                android:value="" />
        </activity>
    </application>

</manifest>

 

gradle.poroperties

# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
# AndroidX package structure to make it clearer which packages are bundled with the
# Android operating system, and which are packaged with your app's APK
# https://developer.android.com/topic/libraries/support-library/androidx-rn
android.useAndroidX=true
# Enables namespacing of each library's R class so that its R class includes only the
# resources declared in the library itself and none from the library's dependencies,
# thereby reducing the size of the R class for that library
android.nonTransitiveRClass=true

# Automatically convert third-party libraries to use AndroidX
android.enableJetifier=true

#test
test =  aaa
##########################################################################
# debug ???? ??
DEBUG_KEYSTORE_FILE = /../jks/debugBank.jks
# release ???? ??
RELEASE_KEYSTORE_FILE = /../jks/releaseBank.jks
# debug ???????
DEBUG_KEY_ALIAS = debugkey
# release ???????
RELEASE_KEY_ALIAS = releaseKey
# debug keyStore ????? --> keyStorePassword
DEBUG_KEYSTORE_PWD = 123456
# debug ????? --> keyPassword
DEBUG_KEY_PWD = 123456
# release keyStore ????? --> keyStorePassword
RELEASE_KEYSTORE_PWD = 123456
# release ????? --> keyPassword
RELEASE_KEY_PWD = 123456

module_a  的 build.gradle

if (Boolean.valueOf(rootProject.ext.isModule_a)) {
    apply plugin: 'com.android.library'
    println "----- module_a Start as library-----"
} else {
    apply plugin: 'com.android.application'
    println "----- module_a Start as application-----"
}

android {
    def versionConfig = rootProject.extensions.getByName("ext").android
    println "---module_a versionConfig is:" + versionConfig

    namespace 'com.demo.module_a'
    compileSdk versionConfig.compileSdkVersion
    buildToolsVersion versionConfig.buildToolsVersion

    defaultConfig {
        // 作为程序独立运行时才设置AppId
        if (!Boolean.valueOf(rootProject.ext.isModule_a)) {
            applicationId "com.demo.module_a"
        }

        minSdk      versionConfig.minSdkVersion
        targetSdk   versionConfig.targetSdkVersion
        versionCode rootProject.ext.android["versionCode"]
        versionName rootProject.ext.android["versionName"]

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        //arouter
        javaCompileOptions {
            annotationProcessorOptions {
                arguments = [ moduleName : project.getName() ]
            }
        }

    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    dataBinding {
        enabled = true
    }

    sourceSets {
        main {
            jniLibs.srcDirs = ['libs']
            if (!Boolean.valueOf(rootProject.ext.isModule_a)) {
                manifest.srcFile 'src/main/AndroidManifest.xml'
            } else {
                manifest.srcFile 'src/debug/AndroidManifest.xml'
            }
        }
    }

}

dependencies {
    // >基础依赖 - 其他模块需要可以单独依赖
    implementation project(':librarys:lib_basic')

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

    //arouter
    implementation rootProject.ext.dependencies["Arouter"]
    annotationProcessor rootProject.ext.dependencies["Arouter-anno"]

}

module_a 的 main/manifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.AgreeBankMVVM">
        <activity
            android:name=".ModuleAMainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>

            <meta-data
                android:name="android.app.lib_name"
                android:value="" />
        </activity>
    </application>

</manifest>

module_a 的 debug/manifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.AgreeBankMVVM">

        <activity
            android:name=".ModuleAMainActivity"
            android:exported="true">
        </activity>


    </application>

</manifest>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值