现在多数android项目开发使用的工具是android studio,所有避免不了需要使用gradle 进行APP打包签名,第三方引入等等,本篇文章涉及 基础配置 ,app自定义包输路径与自动添加日期版本 ,管理第三方依赖,常见问题解决方法
顶层的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运行
签名配置,一般签名账号与密码,敏感信息可以统一进行存放,不进行硬编码
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 文件中
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 输出结果
在顶层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中引入
}
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中引入
}