相信大家的项目用上gradle都已经很久了,但用得如何呢?这里分享一下我的gradle脚本,大部分都是去年6月左右就开始用上的,有一部分比如签名的安全保存则是最近才自己动手,做了令自己觉得还不错的方案。

module类型的区分
科普小结,可能有些同学不太明白Java library module和Android library module是怎么区分的,其实就是个plugin的区别,在module的build.gradle中:

Android application module:


apply plugin: 'com.android.application'

Android library module:


apply plugin: 'com.android.library'

Java library module:

apply plugin: 'java'

版本号管理
如果只有一个application module还好,如果我们有多个module怎么办呢?每次改版本号累不累?

解决方案就是在root里申明全局变量,可以在单独的gradle里(比如新建一个dependency.gradle)申明然后apply from引用进来,或者直接定义在root的build.gradle中。

project.ext {
applicationId = "com.xxx"
buildToolsVersion = "23.0.2"
compileSdkVersion = 23
minSdkVersion = 14
targetSdkVersion = 23
versionCode = 1
versionName = "1.0.0"
abortOnLintError = false
checkLintRelease = false
useJack = false
abortOnLintError = false

javaVersion = JavaVersion.VERSION_1_8
...
}

在子module里面则使用rootProject.ext去进行引用:

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

defaultConfig {
applicationId rootProject.ext.applicationId
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode rootProject.ext.versionCode
versionName rootProject.ext.versionName
multiDexEnabled true
}

compileOptions {
sourceCompatibility rootProject.ext.javaVersion
sourceCompatibility rootProject.ext.javaVersion
}

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

lintOptions {
abortOnError rootProject.ext.abortOnLintError
checkReleaseBuilds rootProject.ext.checkLintRelease
quiet true
ignoreWarnings true
// Some libraries have issues with this.
disable 'InvalidPackage'
// Lint gives this warning but SDK 20 would be Android L Beta.
disable 'OldTargetApi'
}
...

依赖管理
那么多第三方库的引用,在多个module里引用,修改起版本号来好辛苦,万一有一个漏改了(比如gson)结果导致了异常行为,搞不好查原因查个半天,结果摔键盘竟然是版本号导致的。

so,和上节类似,我们需要统一定义依赖:

daggerVersion = "2.0.2"
def retrofitVersion = "2.0.0-beta4"
def supportVersion = "23.2.1"
def rxBindingVersion = '0.4.0'

def leakCanaryVersion = "1.3.1"
def blockCanaryVersion = '1.1.4'

project.ext {
...
libSupportAppcompat = "com.android.support:appcompat-v7:${supportVersion}"
libSupportDesign = "com.android.support:design:${supportVersion}"
libSupportRecyclerview = "com.android.support:recyclerview-v7:${supportVersion}"
libSupportV4 = "com.android.support:support-v4:${supportVersion}"

libRxAndroid = "io.reactivex:rxandroid:1.1.0"
libRxJava = "io.reactivex:rxjava:1.1.1"
libEventBus = "org.greenrobot:eventbus:3.0.0"
libJavaxAnnotation = "javax.annotation:jsr250-api:1.0"

libGson = "com.google.code.gson:gson:2.4"
libRetrofit = "com.squareup.retrofit2:retrofit:${retrofitVersion}"
libRetrofitConverterGson = "com.squareup.retrofit2:converter-gson:${retrofitVersion}"
libRetrofitAdapterRxJava = "com.squareup.retrofit2:adapter-rxjava:${retrofitVersion}"
libOkHttpLoggingInterceptor = "com.squareup.okhttp3:logging-interceptor:3.0.0-RC1"

libDagger = "com.google.dagger:dagger:${daggerVersion}"
libDaggerCompiler = "com.google.dagger:dagger-compiler:${daggerVersion}"

libGlide = "com.github.bumptech.glide:glide:3.7.0"

libRxBinding = "com.jakewharton.rxbinding:rxbinding:${rxBindingVersion}"
libRxBindingSupportV4 = "com.jakewharton.rxbinding:rxbinding-support-v4:${rxBindingVersion}"
libRxBindingAppcompatV7 = "com.jakewharton.rxbinding:rxbinding-appcompat-v7:${rxBindingVersion}"
libRxBindingDesign = "com.jakewharton.rxbinding:rxbinding-design:${rxBindingVersion}"
libRxBindingRecyclerview = "com.jakewharton.rxbinding:rxbinding-recyclerview-v7:${rxBindingVersion}"

libRealm = "io.realm:realm-android:0.87.5"

debugDependencies = [
leakCanary: "com.squareup.leakcanary:leakcanary-android:${leakCanaryVersion}",
blockcanary: "com.github.moduth:blockcanary-ui:${blockCanaryVersion}",
]

releaseDependencies = [
leakCanary: "com.squareup.leakcanary:leakcanary-android-no-op:${leakCanaryVersion}",
blockcanary: "com.github.moduth:blockcanary-no-op:${blockCanaryVersion}",
]
}

这里也可以根据个人喜好把版本号也全都抽出去,我个人的实践原则是除非引用超出1处,否则还是定义在一起。

module中使用:

dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
...
apt rootProject.ext.libDaggerCompiler
compile rootProject.ext.libDagger
compile rootProject.ext.libRxJava
compile rootProject.ext.libRxAndroid
compile rootProject.ext.libRxBinding
compile rootProject.ext.libGlide
provided rootProject.ext.libJavaxAnnotation
compile rootProject.ext.libSupportAppcompat
compile rootProject.ext.libSupportDesign
compile rootProject.ext.libSupportRecyclerview
compile rootProject.ext.libSupportV4
debugCompile rootProject.ext.debugDependencies.leakCanary
releaseCompile rootProject.ext.releaseDependencies.leakCanary
debugCompile rootProject.ext.debugDependencies.blockCanary
releaseCompile rootProject.ext.releaseDependencies.blockCanary
}

这里我还特地为一些debug和release compile不同包的定义了2个map,见leakCanary和blockCanary引用。

签名管理
签名是一个很敏感的东西,只要有了签名文件和对应的密码信息,就能轻易反编译修改源码然后再签名进行发布,因此如何保存这些敏感信息是很重要的。

在我的个人实践中,主要做了这么几点:

local.properties定义keystore信息文件路径:


keystore.props.file=../keystore.properties

keystore.properties保存keystore信息:

store=../buildsystem/release.jks
alias=xxx
storePass=xxx
pass=xxx

buildsystem下保存了:

$ ls
ci.gradle
debug.keystore
release.jks

application module的signingConfigs:

signingConfigs {

def Properties localProps = new Properties()
localProps.load(new FileInputStream(file('../local.properties')))
def Properties keyProps = new Properties()

// 如果读取不到'keystore.props.file'属性,就使用debug keystore

if (localProps['keystore.props.file']) {
keyProps.load(new FileInputStream(file(localProps['keystore.props.file'])))
} else {
keyProps["store"] = '../buildsystem/debug.keystore'
keyProps["alias"] = 'android'
keyProps["storePass"] = 'androiddebugkey'
keyProps["pass"] = 'android'
}

debug {
storeFile file(keyProps["store"])
keyAlias keyProps["alias"]
storePassword keyProps["storePass"]
keyPassword keyProps["pass"]
}

release {
// release版本使用assert确保存在该属性否则报错,避免错误打包
assert localProps['keystore.props.file'];
storeFile file(keyProps["store"])
keyAlias keyProps["alias"]
storePassword keyProps["storePass"]
keyPassword keyProps["pass"]
}
}

Java8支持
对Android的module

apply plugin: 'me.tatarka.retrolambda'

android {
compileOptions {
sourceCompatibility rootProject.ext.javaVersion
sourceCompatibility rootProject.ext.javaVersion
}
}

对Java的module:


sourceCompatibility = 1.8
targetCompatibility = 1.8

Split APK
详细的可以看看Google的官方文档Apk Splits

我的使用:



splits {
abi {
enable true
reset()
include 'armeabi', 'x86' //, 'x86', 'armeabi-v7a', 'mips'
universalApk false
}
}

大致来说,就是可以根据脚本的配置,将apk以abi、density进行分包。再也不用为了缩小包的体积而专门去只留下一个arm的jni文件夹了,想怎么分怎么分,搞不定哪天就要传一个x86的包了,而且有的模拟器也只支持x86。

当然如果市场能支持这些配置,那就更好了,用户下载apk的流量就小多了。

Module aar依赖
怎么能在使用aar依赖提升编译速度的同时,又能兼顾灵活性,随时可以修改源码呢?

解决方案就是module式aar依赖。

在你的library module目录下, 打开build/outputs/aar,是不是有aar文件(编译过后就会生成)?把它放到module目录下面,然后在build.gradle里面:

configurations.maybeCreate("default")
artifacts.add("default", file('lib_authorize-debug.aar'))

再把原来那些脚本给注释了,就搞定了。是不是特别简单?如果想再使用源码依赖,反注释一下就好了。

总结
本篇主要讲了开发阶段gradle的各种实践,下一篇是什么暂时我也没有想法,哈哈。

Gradle #New Android Project From 0

更多相关文章

  1. 多个dex文件定义了Landroid/支持/v13/app/FragmentCompatICS。
  2. 自定义BaseAdapter,在主Activity页面调用显示歌曲列表
  3. Android 自定义控件高度设置onMeasure方法
  4. Android自定义View-----上下拖动布局--SlideContentLayout
  5. Android从零开搞系列:自定义View(15)仿天天美剧拖动卡片的效果(下)
  6. DialogFragment自定义dialog的位置和大小
  7. 如何使用2个旋转圆圈获得与ICS相同的未定义ProgressBar?
  8. java常量的定义
  9. 自定义标签 Unable to find setter method for attribute

随机推荐

  1. php调停者模式(mediator pattern)
  2. 在ThinkPhp中实现无限极分类
  3. 用于检查用户名可用性的Javascript帖子无
  4. 管理大量文件的提示?
  5. PHP正则表达式
  6. PHP代码在不需要时在Javascript中自动运
  7. Web2.0 (social media) 企业应用的架构
  8. HTML5关于get请求添加headers的问题
  9. 在页面重新加载时添加活动链接和jquery幻
  10. 采集资源的方法(文字,图片) [图片]