从零开始的Android新项目2 - Gradle篇

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

module类型的区分

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

Android application module:

      
1
      
apply plugin: 'com.android.application'

Android library module:

      
1
      
apply plugin: 'com.android.library'

Java library module:

      
1
      
apply plugin: 'java'

版本号管理

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

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

      
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
      
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去进行引用:

      
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
      
android {
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,和上节类似,我们需要统一定义依赖:

      
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
      
def 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}"</span></div><div class="line"> libSupportDesign = <span class="string">"com.android.support:design:${supportVersion}"
libSupportRecyclerview = "com.android.support:recyclerview-v7:${supportVersion}"</span></div><div class="line"> libSupportV4 = <span class="string">"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}"</span></div><div class="line"> libRetrofitConverterGson = <span class="string">"com.squareup.retrofit2:converter-gson:${retrofitVersion}"
libRetrofitAdapterRxJava = "com.squareup.retrofit2:adapter-rxjava:${retrofitVersion}"</span></div><div class="line"> libOkHttpLoggingInterceptor = <span class="string">"com.squareup.okhttp3:logging-interceptor:3.0.0-RC1"</span></div><div class="line"></div><div class="line"> libDagger = <span class="string">"com.google.dagger:dagger:${daggerVersion}"
libDaggerCompiler = "com.google.dagger:dagger-compiler:${daggerVersion}"</span></div><div class="line"></div><div class="line"> libGlide = <span class="string">"com.github.bumptech.glide:glide:3.7.0"</span></div><div class="line"></div><div class="line"> libRxBinding = <span class="string">"com.jakewharton.rxbinding:rxbinding:${rxBindingVersion}"
libRxBindingSupportV4 = "com.jakewharton.rxbinding:rxbinding-support-v4:${rxBindingVersion}"</span></div><div class="line"> libRxBindingAppcompatV7 = <span class="string">"com.jakewharton.rxbinding:rxbinding-appcompat-v7:${rxBindingVersion}"
libRxBindingDesign = "com.jakewharton.rxbinding:rxbinding-design:${rxBindingVersion}"</span></div><div class="line"> libRxBindingRecyclerview = <span class="string">"com.jakewharton.rxbinding:rxbinding-recyclerview-v7:${rxBindingVersion}"
libRealm = "io.realm:realm-android:0.87.5"
debugDependencies = [
leakCanary: "com.squareup.leakcanary:leakcanary-android:${leakCanaryVersion}"</span>,</div><div class="line"><span class="symbol"> blockcanary:</span> <span class="string">"com.github.moduth:blockcanary-ui:${blockCanaryVersion}",
]
releaseDependencies = [
leakCanary: "com.squareup.leakcanary:leakcanary-android-no-op:${leakCanaryVersion}"</span>,</div><div class="line"><span class="symbol"> blockcanary:</span> <span class="string">"com.github.moduth:blockcanary-no-op:${blockCanaryVersion}",
]
}

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

module中使用:

      
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
      
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信息文件路径:

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

keystore.properties保存keystore信息:

      
1
2
3
4
      
store=../buildsystem/release.jks
alias=xxx
storePass=xxx
pass=xxx

buildsystem下保存了:

      
1
2
3
4
      
$ ls
ci.gradle
debug.keystore
release.jks

application module的signingConfigs:

      
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
      
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

      
1
2
3
4
5
6
7
8
      
apply plugin: 'me.tatarka.retrolambda'
android {
compileOptions {
sourceCompatibility rootProject.ext.javaVersion
sourceCompatibility rootProject.ext.javaVersion
}
}

对Java的module:

      
1
2
      
sourceCompatibility = 1.8
targetCompatibility = 1.8

Split APK

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

我的使用:

      
1
2
3
4
5
6
7
8
      
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里面:

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

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

总结

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

转自:http://blog.zhaiyifan.cn/2016/03/14/android-new-project-from-0-p2/

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页