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

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

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

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}"
    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中使用:

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的各种实践,下一篇是什么暂时我也没有想法,哈哈。

ps:最近有些忙版本的事,有写的内容,没时间写,看到一些好文,跟大家分享一下,顺便收藏。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Gradle 是一种高度灵活的自动化构建工具,它可以用于构建各种类型的项目,如 Java 应用程序、Android 应用程序、Web 应用程序等。本文将介绍如何从零开始使用 Gradle 构建一个简单的 Java 应用程序。 1. 安装 Gradle 首先需要安装 Gradle,可以从官网下载最版本。下载完成后,解压缩到任意目录,并将其 bin 目录加入系统 PATH 环境变量中。 2. 创建项目 在任意目录下创建一个目录,作为项目的根目录。在该目录下创建以下目录结构: ``` src/ main/ java/ com/ example/ HelloWorld.java resources/ build.gradle ``` 其中,src/main/java/com/example/HelloWorld.java 是我们要编写的 Java 类,build.gradleGradle 的构建脚本。 3. 编写 Java 类 在 src/main/java/com/example 目录下创建一个的 Java 类,名为 HelloWorld。这个类将包含一个 main 方法,用于输出一个简单的字符串: ``` package com.example; public class HelloWorld { public static void main(String[] args) { System.out.println("Hello, world!"); } } ``` 4. 编写构建脚本 在项目根目录下创建 build.gradle 文件,这是 Gradle 的构建脚本。在这个文件中,我们将定义如何编译和打包我们的 Java 应用程序。 ``` apply plugin: 'java' repositories { jcenter() } dependencies { // 指定使用的 Java 版本 compileJava.options.encoding = 'UTF-8' sourceCompatibility = 1.8 targetCompatibility = 1.8 } task buildJar(type: Jar) { // 指定打包生成的 JAR 文件名 archiveName = "hello-world.jar" // 将编译后的类文件添加到 JAR 文件中 from sourceSets.main.output // 将 MANIFEST.MF 文件添加到 JAR 文件中 manifest { attributes "Main-Class": "com.example.HelloWorld" } } // 定义默认任务 defaultTasks 'build' ``` 这个构建脚本中包含了以下几个部分: - apply plugin: 'java':表示我们要使用 Java 插件。 - repositories:指定项目使用的仓库,这里我们使用 jcenter。 - dependencies:指定项目的依赖,这里我们没有依赖任何库。 - task buildJar(type: Jar):定义一个名为 buildJar 的任务,用于打包我们的应用程序。 - archiveName:指定打包生成的 JAR 文件名。 - from sourceSets.main.output:将编译后的类文件添加到 JAR 文件中。 - manifest:指定 JAR 文件的 MANIFEST.MF 文件,其中包含了 Main-Class 属性,指定了程序的入口点。 - defaultTasks 'build':定义默认任务为 build。 5. 执行构建 在项目根目录下执行以下命令: ``` gradle build ``` 这个命令将会执行 build 任务,该任务将会编译 Java 代码并打包生成 JAR 文件。在执行完毕之后,可以在 build/libs 目录下找到生成的 JAR 文件。 6. 运行应用程序 在命令行中执行以下命令,即可运行我们的应用程序: ``` java -jar build/libs/hello-world.jar ``` 这个命令将会启动 Java 虚拟机,并执行我们打包生成的 JAR 文件。在控制台中会输出 "Hello, world!" 字符串。 至此,我们成功构建了一个简单的 Java 应用程序,并使用 Gradle 进行了自动化构建。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值