(四)项目实战之Gradle

现在多数android项目开发使用的工具是android studio,所有避免不了需要使用gradle 进行APP打包签名,第三方引入等等,本篇文章涉及 基础配置 ,app自定义包输路径与自动添加日期版本 ,管理第三方依赖,常见问题解决方法

1.基础配置

顶层的build.gradle:顶层的build.gradle文件的配置最终会被应用到所有项目中。典型的配置如下

buildscript {
    repositories {
        jcenter()
    }

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

allprojects{
    repositories{
        jcenter()
    }
}

每个lib都有一个独立build.grade典型的配置如下

apply plugin: 'com.android.application'
android {
    compileSdkVersion 27
    defaultConfig {
        applicationId "com.sfh.pluginchild"
        minSdkVersion 15
        targetSdkVersion 27
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:27.1.1'
} 
  • apply plugin:用于标识当前Module 类型
    1. com.android.application 表示此Module 是为当前项目主程app 可编译运行
    2. com.android.library 标识此Module只能最为引入库使用不能编译成app运行

  • buildTypes:定义了编译类型,针对每个类型我们可以有不同的编译配置,不同的编译配置对应的有不同的编译命令。默认的有debug、release 的类型。
  • dependencies:gradle 的依赖配置。定义了当前项目需要依赖的其他库。

签名配置,一般签名账号与密码,敏感信息可以统一进行存放,不进行硬编码

android{
...

    buildTypes {

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

   //签名配置
    signingConfigs {
        debug {
            v1SigningEnabled true
            v2SigningEnabled true
        }

        release {
            storeFile
            storePassword
            keyAlias
            keyPassword
            v1SigningEnabled true
            v2SigningEnabled true
        }
    }
    
    //读取签名信息
    getSigningProperties()

}

//读取签名配置文件
def getSigningProperties() {
    Properties props = new Properties()
    props.load(new FileInputStream(new File('setting.properties')))
    if (props != null) {

        android.signingConfigs.release.storeFile = file(props['SIGN_HOME'])
        android.signingConfigs.release.storePassword = props['SIGN_STORE_PASSWORD']
        android.signingConfigs.release.keyAlias = props['SIGN_KEY_ALIAS']
        android.signingConfigs.release.keyPassword = props['SIGN_KEY_PASSWORD']

    } else {
        println 'setting.properties not found'
        android.buildTypes.release.signingConfig = null
    }
}

我们把签名敏感信息以key-value形式放在setting.properties 文件中

(四)项目实战之Gradle_第1张图片

2.app自定义包输位置与自动添加日期版本

android{
...
  //release版本输出包名自动追加版本号和版本名称
    applicationVariants.all {
        variant ->
            variant.outputs.all {
                if (buildType.name == 'release'){
                    outputFileName = "app_v" + defaultConfig.versionName + "_" + new Date().format("yyyy-MM-dd") + "_" + buildType.name + ".apk"
                }
            }
    }

    buildTypes {

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

        //指定APP输出文件夹
        applicationVariants.all {
            //指定release输出到指定文件夹
            if (it.buildType.name == 'release'){
                def createTime = new Date().format("YYYY-MM-dd", TimeZone.getTimeZone("GMT+08:00"))
                it.getPackageApplication().outputDirectory = new File("定义输出路径" + "/${createTime}")
            }
        }
    }
}

编译项目APK 输出结果

(四)项目实战之Gradle_第2张图片

3.依赖包管理

在顶层build.gradle 中进行统一配置与版本号控制,方便管理。把内容添加在最下面

ext {
    //配置
    config = [
            compileSdkVersion: 26,        // 编译版本
            buildToolsVersion: '26.0.2',  // 编译工具版本
            minSdkVersion    : 15,        // 最低版本
            targetSdkVersion : 22,         // 目标版本
            versionCode : 1,
            flavorDimensions  : "owner",
            versionName :'1.0.0',
            appReleaseDir : 'F:\\out_apk\\owner' //打包输出路径
    ]

    //依赖库
    libs = [
            android_multidex      : 'com.android.support:multidex:1.0.3',
            android_supportV7     : 'com.android.support:appcompat-v7:27.1.0',

            comm_rft              : 'com.squareup.retrofit2:retrofit:2.4.0'

    ]
}

在需要使用的module 项目中使用

android{
      compileSdkVersion config.compileSdkVersion

       defaultConfig {
           minSdkVersion config.minSdkVersion
           targetSdkVersion config.targetSdkVersion
           versionCode config.versionCode
           versionName config.versionName
     }
}
dependencies {
  ...
  compile libs.android_multidex             // 分包 必须APP中引入
}

4.常见问题

1.gradle 编译工具升级3.0时需要注意在defaultconfig中新增配置属性,否则出现编译异常

Error:All flavors must now belong to a named flavor dimension. Learn more athttps://d.android.com/r/tools/flavorDimensions-missing-error-message.html

解决方式:添加依赖匹配,与版本一致即可

 defaultConfig {
      
        flavorDimensions config.flavorDimensions
    
    }

2.需要在项目结构中,直观看到引入哪些libs包?解决方式:在android{}中添加如下配置即可


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

3.当项目中依赖的第三方库越来越多时,可能会出现两个依赖库中存在同一个(名称)文件。如果这样,Gradle在打包时就会提示错误(警告)。那么就可以根据提示,使用以下方法将重复的文件剔除。

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

4.自动代码检查,防止代码不符合规范导致编译失败

 lintOptions {
        abortOnError false
        checkReleaseBuilds false
        // 防止在发布的时候出现因MissingTranslation导致Build Failed!
        disable 'MissingTranslation'
        disable 'DuplicateIds'
        disable 'ValidFragment'
        disable 'LongLogTag'
    }

最终完整build.gradle

apply plugin: 'com.android.application'

android {

    compileSdkVersion config.compileSdkVersion
    buildToolsVersion config.buildToolsVersion

    defaultConfig {
        applicationId "com.sfh.cpc"
        minSdkVersion config.minSdkVersion
        targetSdkVersion config.targetSdkVersion
        versionCode config.versionCode
        flavorDimensions config.flavorDimensions
        versionName config.versionName
        multiDexEnabled true
        ndk {
            //选择要添加的对应cpu类型的.so库。
            abiFilters 'armeabi', 'armeabi-v7a'
        }
    }

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

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

    lintOptions {
        abortOnError false
        checkReleaseBuilds false
        // 防止在发布的时候出现因MissingTranslation导致Build Failed!
        disable 'MissingTranslation'
        disable 'DuplicateIds'
        disable 'ValidFragment'
        disable 'LongLogTag'
    }

    dexOptions {
        javaMaxHeapSize "4g"
    }

    //多渠道打包
    productFlavors {
        zczyOwenr {
            manifestPlaceholders = [appName: "ownerMAA"]
            dimension config.flavorDimensions
        }
    }
    //签名配置
    signingConfigs {
        debug {
            v1SigningEnabled true
            v2SigningEnabled true
        }

        release {
            storeFile
            storePassword
            keyAlias
            keyPassword
            v1SigningEnabled true
            v2SigningEnabled true
        }
    }

    getSigningProperties()

    //release版本输出包名自动追加版本号和版本名称
    applicationVariants.all {
        variant ->
            variant.outputs.all {
                if (buildType.name == 'release'){
                    outputFileName = "app_v" + defaultConfig.versionName + "_" + new Date().format("yyyy-MM-dd") + "_" + buildType.name + ".apk"
                }
            }
    }

    buildTypes {
        debug {
            debuggable true  //启用debug的buildType配置
            signingConfig signingConfigs.release
        }
        release {
            minifyEnabled false
            signingConfig signingConfigs.release
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }

        //输出类型
        applicationVariants.all {
            //指定release输出到指定文件夹
            if (it.buildType.name == 'release'){
                def createTime = new Date().format("YYYY-MM-dd", TimeZone.getTimeZone("GMT+08:00"))
                it.getPackageApplication().outputDirectory = new File(config.appReleaseDir + "/${createTime}")
            }
        }
    }
}

//读取签名配置文件
def getSigningProperties() {
    Properties props = new Properties()
    props.load(new FileInputStream(new File('setting.properties')))
    if (props != null) {

        android.signingConfigs.release.storeFile = file(props['SIGN_HOME'])
        android.signingConfigs.release.storePassword = props['SIGN_STORE_PASSWORD']
        android.signingConfigs.release.keyAlias = props['SIGN_KEY_ALIAS']
        android.signingConfigs.release.keyPassword = props['SIGN_KEY_PASSWORD']

    } else {
        println 'setting.properties not found'
        android.buildTypes.release.signingConfig = null
    }
}

dependencies {

    compile project(':Lib_Base_SDK')  // 基本框架层
  
    compile libs.android_multidex             // 分包 必须APP中引入

}

 

你可能感兴趣的:(Android项目实战,Android项目开发实践)