Build Android Project with Gradle

相温文
2023-12-01

现在随着友盟这类统计工具在项目中集成,根据不同渠道打不同的APK包也成为日常工作之一。神马?你还在手动改渠道号一个一个打包?!那你一定是个非常勤奋的程序员- -!正好尝试使用Android Studio,稍微了解了下Android Studio的使用的构建工具:Gradle。

什么是Gradle

你可以看一下Gradle主页

简单来说,Gradle是一个自动化编译部署测试工具。Gradle内容很广,还有专门的书介绍Gradle。而Android Studio使用的是Gradle中的一部分功能。

build.gradle

build.gradle就是Android Studio使用的Gradle文件,下面是一个最简单的build.gradle示例:

buildscript {
    repositories {
        mavenCentral()
    }

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

apply plugin: 'android'

android {
    compileSdkVersion 17
}

buildscript {...} 配置编译代码,这部分基本上不用怎么编辑;

apply plugin: 'android' 是表示用android插件;

android {...} 就是android插件的配置了。具体配置内容以及取值可以看这里

Build Task

Gradle中用Task来代表一系列操作,有点类似于Makefile中的Target。常见的Tasks有:

  • assemble
  • build
  • check
  • clean

根据名字基本就能知道Task作用,其中build = assemble + check。

执行task直接就是在命令行执行gradle [task],例如: gradle assemble

gradle assembleRelease

Build参数配置

Gradle脚本中的参数是DSL规范的,即使用的是类似于Java包名的方式:

a.b.c = 1

a {
    b {
      c 1        
    }
}

上面两种方式表示的是一个意思。 可以配置的参数这里不做详述,请到http://tools.android.com/tech-docs/new-build-system/user-guide查阅。

下面讲几个主要使用的参数。

Build Types

TODO

Signing Configurations

在生成APK的时候,有一步是用一个Key给APK签名,关于签名的配置项都在signingConfigs中:

signingConfigs {
    myConfig {
        storeFile file("path-to-keystore")
        storePassword "******"
        keyAlias "******"
        keyPassword "******"
    }
}
然后在编译类型中引用:
buildTypes {
    release {
        ...
        signingConfig signingConfigs.myConfig
    }
}
这样签名的配置就好了。不过按上文配置,有一个问题:build.gradle经常是会提交到代码管理系统中,而显然把key明文放在代码库里不怎么安全(特别如果你写的是开源项目)。一个替代的方案是输入密码,或者将密码存储在环境变量中,可以参看这个链接: http://stackoverflow.com/questio ... k-file-using-gradle
... 
signingConfigs {
    release {
        storeFile file(System.getenv("KEYSTORE"))
        storePassword System.getenv("KEYSTORE_PASSWORD")
        keyAlias System.getenv("KEY_ALIAS")
        keyPassword System.getenv("KEY_PASSWORD")
    }
}

Product flavors

如果你一个项目想要生成不同的APK包,有不同的包名,或者不同的资源,那么这就是使用Product flavors的时候了。

android {
    ....

    productFlavors {
        flavor1 {
            packageName "com.example.flavor1"
            versionCode 20
        }

        flavor2 {
            packageName "com.example.flavor2"
            minSdkVersion 14
        }
    }
}

上面的示例会生成两个不同的APK包,有着不同的包名以及属性。Product flavors里边可以设置的属性,参照http://tools.android.com/tech-docs/new-build-system/user-guide

友盟多渠道打包

看了上面这么多,现在来一个示例:写一个build.gradle完成友盟多渠道打包。 友盟渠道区分是通过在AndroidManifest.xml的<meta-data>实现的:

<meta-data android:value="UMENG_CHANNEL_VALUE" android:name="UMENG_CHANNEL"/>
所以基本的思路就是,在打包的时候替换AndroidManifest.xml中的字符串以打出不同的APK包。 build.gradle关键部分如下:
android {
    compileSdkVersion 19
    buildToolsVersion '19.0.0'

    defaultConfig {
        minSdkVersion 7
        targetSdkVersion 19
    }

    // 签名信息,都存在环境变量中
    signingConfigs {
        release {
            storeFile file(System.getenv("KEYSTORE"))
            storePassword System.getenv("KEYSTORE_PASSWORD")
            keyAlias System.getenv("KEY_ALIAS")
            keyPassword System.getenv("KEYSTORE_PASSWORD")
        }
    }


    buildTypes {
        release {
            runProguard true
            proguardFile getDefaultProguardFile('proguard-android-optimize.txt')
            signingConfig signingConfigs.release  //使用上述签名信息
        }
    }
    productFlavors {
        defaultFlavor {
            proguardFile 'proguard-rules.txt'
        }
        // 需要打不同的版本
        xiaomi {
        }
        LeTv {
        }
    }
}

// 下面这段代码摘自 <a href="https://github.com/umeng/umeng-muti-channel-build-tool/tree/master/Gradle" target="_blank" style="color: rgb(0, 136, 204); text-decoration: none;">https://github.com/umeng/umeng-muti-channel-build-tool/tree/master/Gradle</a>
// 实现用productFlavor名字替换AndroidManifest.xml 中的 UMENG_CHANNEL_VALUE 字符串
android.applicationVariants.all { variant ->
    variant.processManifest.doLast{
        copy{
            from("${buildDir}/manifests"){
                include "${variant.dirName}/AndroidManifest.xml"
            }
            into("${buildDir}/manifests/$variant.name")

            filter{
                String line -> line.replaceAll("UMENG_CHANNEL_VALUE", "${variant.productFlavors[0].name}")
            }

            variant.processResources.manifestFile = file("${buildDir}/manifests/${variant.name}/${variant.dirName}/AndroidManifest.xml")
        }
    }
}

在修改完build.gradle之后,需要使用Android Studio的sync Project with gradle files功能同步工程设置。 之后就在Android Studio的Terminal中输入gradle build(windows是gradlew build),稍等片刻,所有生成的APK都在你工程的build/apk下了!

 类似资料:

相关阅读

相关文章

相关问答