通过这篇文章,你可以简单实现多渠道,或者说定制化的apk打包,实现一次打包多个apk,充分了解gradle的各项配置,解决资源冲突问题。

as 的gradle配置主要分为三种:

1、项目全局配置的build.gradle

2、每个moudle 下的build.gradle

3、自定义的xxx.gradle (xxx为自定义文件名)

下面对这些配置进行逐一讲解

自定义xxx.gradle

在项目目录下新建一个config.gradle文件(名字自定义)
/**
 * 自定义参数,必须为ext ,因为该字段为gradle默认的扩展属性配置
 *
 * 使用:
 * 在需要引用该文件的moudle/build.gradle 顶部输入:apply from: "config.gradle"
 * 这条命令指明把这个config.gradle 的配置加载到当前gradle配置中,如果在项目的build.gradle
 * 引入,则该配置为全局配置,可在项目中任意moudle的gradle中使用。
 *
 * 引用自定义的值:
 * 在moudle中引入:${"project.ext.android.versionName"}
 * 在项目moudle中引入:${"rootProject.ext.android.versionName"}
 *
 * 注意:
 * 引用时要使用双引号,单引号不会解释变量,直接作为字符串,双引号才会解释变量
 * println("${project.ext.android.versionCode}")输出:1
 * println('${project.ext.android.versionCode}')输出:${project.ext.android.versionCode}
 *
 * def修饰的对象无法在当前文件外引用
 *
 * 使用这种方式配置项目,方便项目的迁移,或者各个moudle的统一引用,最重要的是B格高
 *
 */

ext{

    android = [
            compileSdkVersion: 26,
            buildToolsVersion: '27.0.3',
            applicationId    : "com.dzt.launchmode",
            minSdkVersion    : 15,
            targetSdkVersion : 26,
            versionCode      : 1,
            versionName      : "1.0"
    ]
    //只能内部使用
    def dependVersion = [
            support    : "26.+",
            retrofit   : "2.1.0",
            butterknife: "8.4.0",
            blockcanary: "1.2.1",
            leakcanary : "1.4-beta2"
    ]

    dependencies = [
            "appcompat-v7"                   : "com.android.support:appcompat-v7:${dependVersion.support}",
            "recyclerview-v7"                : "com.android.support:recyclerview-v7:${dependVersion.support}",
            "design"                         : "com.android.support:design:${dependVersion.support}",
      ]

}

项目build.gradle配置

//该配置用于引入自定义的gradle配置文件
apply from:'config.gradle'
//buildScript是用来加载gradle脚本自身需要使用的资源,可以声明的资源包括依赖项、第三方插件、maven仓库地址等
buildscript {
    //指定仓库地址
    repositories {
        //google仓库
        google()
        //maven的中心仓库
        jcenter()

    }
    //依赖库
    dependencies {
//        classpath一般是添加buildscript本身需要运行的东西
        classpath 'com.android.tools.build:gradle:3.6.3'
        //接入firebasse
//        classpath 'com.google.gms:google-services:4.3.3'
//        classpath 'com.kezong:fat-aar:1.2.11'
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}
//配置工程所需仓库、依赖项
allprojects {
    repositories {
        google()
        jcenter()
        //本地仓库(默认用户名/.m2/repository)
//        mavenLocal()
        //指定仓库地址
//        maven { url 'D://Users/maven' }
    }
}
//事务,可以自定义,这里是清除build目录缓存
task clean(type: Delete) {
    delete rootProject.buildDir
}

//自定义参数,和config.gradle配置一样
//ext {
//    compileSdkVersion = 28
//    supportLibVersion = "28.0.0"
//}

moudle下的build.gradle配置

//该配置指明该moudle是一个library库,不是一个应用库
apply plugin: 'com.android.library'
//该配置用于引入自定义的gradle配置文件
//apply from: "../config.gradle"

//该moudle的编译环境,参数配置
android {
    //指定编译的版本
    compileSdkVersion 26
    //指定构建版本
    buildToolsVersion "29.0.2"
    //示例引用自定义的值
//    buildToolsVersion ${"rootProject.ext.android.buildToolsVersion"}


    defaultConfig {
        //指定apk最低支持的os版本
        minSdkVersion 19
        //指定apk目标运行版本
        targetSdkVersion 26
        //开发版本号
        versionCode 2
        //用户能看到的版本号
        versionName "1.0.2"

        //开启分包(当方法数超过时会生成多个dex)
//        multiDexEnabled true

        //指定打包时添加的so库版本
//        ndk {
//            abiFilters "armeabi", "armeabi-v7a", "x86"
//        }
    }

    //签名配置
    signingConfigs {
        //release只是一个名称,可自定义
        release {
            //签名别名
            keyAlias 'test'
            //别名密码
            keyPassword 'test12'
            //签名文件
            storeFile file('../test.jks')
            //签名密码
            storePassword 'test12'
            //是否使用v2签名
            v2SigningEnabled false  //禁用v2签名
        }
        debug {
            //签名别名
            keyAlias 'test'
            //别名密码
            keyPassword 'test12'
            //签名文件
            storeFile file('../test.jks')
            //签名密码
            storePassword 'test12'
            //是否使用v2签名
            v2SigningEnabled false  //禁用v2签名
        }

        test {
            //签名别名
            keyAlias 'test'
            //别名密码
            keyPassword 'test12'
            //签名文件
            storeFile file('../test.jks')
            //签名密码
            storePassword 'test12'
            //是否使用v2签名
            v2SigningEnabled false  //禁用v2签名
        }
    }

    //构建类型配置(必须在signingConfigs配置后面)
    buildTypes {
        release {
            //启用资源优化压缩
//            shrinkResources true
//            //启用代码优化
//            minifyEnabled true
            //指定使用哪个签名配置
            signingConfig signingConfigs.release
            //启用代码混淆 proguard-android-optimize.txt:为基本混淆配置默认即可,proguard-rules.pro:扩展混淆配置
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'

        }
        debug {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
        mytest {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }

//    维度,一维(值可自定义,维度也可自定义,用,分隔开,可以自定构建apk,实现打包多个apk,差异化打包apk)
//    flavorDimensions "flavor"
//    二维(值可自定义,维度也可自定义,用,分隔开)
    flavorDimensions "modelA", "modelB"

    /**
     * 参考文档:https://juejin.im/entry/5a586bfaf265da3e2c3808c5
     * 上面定义两个维度,modelA,modelB,下面就通过这两个维度配置差异化apk
     * 配置好productFlavors后,项目编译时会生成四个apk
     * demoAtestADebug
     * demoAtestARelease
     * demoBtestADebug
     * demoBtestARelease
     * 由此可见编译时会把你所有配置的维度组合打包各种差异化的apk
     */
    productFlavors {
        demoA {
            //配置使用哪个维度
            dimension "modelA"
            //配置差异化信息
            applicationId "com.ckj.myapplication1"
            versionCode 1
            versionName "1.0"
            /**
             * 定义占位符,可以androidmanifest.xml中使用:
             *                 <meta-data
             *         android:name="UMENG_CHANNEL"
             *         android:value="${UMENG_CHANNEL_VALUE}" />
             */
            manifestPlaceholders = [UMENG_CHANNEL_VALUE:"value1"]
        }
        demoB {
            dimension "modelA"
            /**
             * 自定义常亮值,添加完后同步下Gradle就可以在编译生成目录
             * (app/build/generated/source/buildConfig)下的BuildConfig.java
             * 参数代表意义:数据类型、键、值
             */
            buildConfigField "boolean", "SUPPORT_AUTO_UPDATE_FEATURE", "false"
        }
        testA {
            dimension "modelB"
        }

    }
    /**
     * demoA上面是配置版本,参数信息,sourceSets是配置代码,资源(aidl、assets、res、jni...)信息
     */
    sourceSets {
        //main是默认source
        main {
            jniLibs.srcDirs = ['libs']
        }

        //这个demoA需要在productFlavors中配置
        demoA{
            /**
             * 需要在src新建一个model/java
             * 注意:main目录下的代码是会和model/java下的代码合并打包到apk的
             * 并不是只打包model/java,所以model/java只适合存放差异化代码,这个目录是可自定义的
             */
            java.srcDirs('src/model/java')
            //需要在src新建一个model/assets
            assets.srcDirs('src/model/assets')
            //类推
            aidl.srcDirs('src/model/aidl')
            res.srcDirs('src/model/res')
            jniLibs.srcDirs('src/model/libs')

        }

    }

    /**
     * 也是从不同维度切分apk,使apk体积缩小
     * 参考文档:https://juejin.im/post/5ddfe513e51d45027e2a7e96
     */
    splits {
        //根据像素切分
        density {
            //是否开启切分
            enable true
            //去掉这些像素,只打包其他尺寸apk,例如:hdpi_apk,xxhdpi_apk...
            exclude "ldpi", "tvdpi", "xxxhdpi", "400dpi", "560dpi"
        }
        //根据架构切分
        abi {
            enable true
            exclude 'x86','arm64-v8a'
            // 重置包含的目录,因为已经是包含全部
            reset()
            // 设置包含,只打包这些架构的apk,调用前需要先用 reset 将默认清除
            include 'armeabi-v7a', 'x86'
            // 是否打出包含全部的apk,包含全部架构的apk
            universalApk true
        }
        //根据语言切分
        language {
            enable = true
            //同理:include包含,exclude:剔除
            include "fr", "zh", "en"
        }
    }

}
//仓库
repositories {
    flatDir {
        dirs 'libs'   // aar目录
    }
}

/**
 * 添加依赖有两种方式:api、implementation
 * api:如果其他moudle引用了该moudle,则其他moudle也可以使用该moudle的依赖库
 * implementation:其他moudle无法使用该moudle的依赖库
 *
 * 注:gradle引用远程库,如果存在相同库,默认会引入高版本的
 * 所以出现版本冲突都是和本地库的冲突,解决方式是删除本地库,或者剔除远程库
 */

//该moudle的依赖配置
dependencies {
    //把一个文件夹里的所有.jar文件都添加进来,可减少本地库的逐个依赖配置
    api fileTree(include: ['*.jar'], dir: 'libs')
    //引入一个moudle
    api project(':overseas')
    //引入一个远程第三方库
    api('com.squareup.retrofit2:retrofit:2.2.0')
    //引入本地库,注意是带有files的
    api files('alipaysdk_15.7.3.jar','gson-2.5.jar')

    //引用本地aar,name:库名 ext:库类型(同时需要制定aar的存放路径,具体参考上面的仓库配置repositories)
    api(name: 'zbar-core', ext: 'aar')

    //引入一个远程第三方库
    implementation ('com.squareup.retrofit2:retrofit:2.2.0'){
        /**
         * exclude用来剔除传递依赖的库
         * 示例解释:
         * group:代表依赖库的组,一个组可以有多个module(分支)
         * module:代表这个组下面的某个分支
         * 如果不填写moudle,就会把整个group都剔除,所以需要根据实际情况剔除
         */
        exclude(group:'com.squareup.okio',module:'okio')
    }

    implementation ('com.android.support:appcompat-v7:26.0.0') {
        /**
         * 不指定group,gralde会默认使用引用库的group
         * 如下:group=com.android.support
         */
        exclude (module: 'support-v4')
    }

    //效果等同:implementation 'com.android.support:multidex:1.0.1'
    implementation group: 'com.android.support', name: 'multidex', version: '1.0.1'

    //只有在构建demoA时才会引入该库
    demoAApi('com.squareup.retrofit2:retrofit:2.2.0')
    //只有在构建demoB时才引入该库(语法:构建类型demoA(在productFlavors中的配置)+Api(或Implementation))
    demoBApi files('alipaysdk_15.7.3.jar','gson-2.5.jar')

}

//自定任务,这里是打包一个jar包
task makeJar(type: Copy) {
    //打印信息
    println("core_${project.ext.android.versionCode}.jar")
    from('build/intermediates/aar_main_jar/debug/classes.jar', configurations.compile)
    into('build/outputs/jar')
    rename('classes.jar', "core_${project.ext.android.versionCode}.jar")
}
//把这个任务添加到build之后, 先执行build,再执行该任务
makeJar.dependsOn(build)

如有错误还请大神指出,谢谢