Gradle打包APK的一些小技巧和productFlavor配置

前言

在使用Gradle来打包Android应用以前,Android自动化打包一般会选择使用ant,ant是一种一步一步来执行任务的工具,一般打包一个apk要通过一个复杂的过程,ant工具经过一步一步完成这些过程来生成一个apk。若是要实现一个复杂一点的打包过程,它的xml配置文件的长度也是足以让你崩溃的。Gradle的出现让打包过程变得十分轻松,并且配置起来也是简单易懂。之前须要写好几天的配置文件如今只要简单的几步就能完成,配合Android Studio更加驾轻就熟。android

一个完整的打包流程以下: picapp

基本的build.gradle

若是你用Android Studio生成一个项目的话,在app模块中你会看到一个build.gradle文件,这个文件就是配置这个模块的地方,大体文件结构以下:ide

apply plugin: 'com.android.application'

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.2"

    defaultConfig {
        minSdkVersion 8
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:19.0.1'
}

这里就不一行行地解释了,关于Gradle的语法能够自行Google。工具

这里主要有两个小技巧gradle

  1. 签名:开发App时常常遇到Release版和Debug版共存问题,因为默认的签名不一样,常常要卸载Debug版安装Release版,很是麻烦。有两种方法能够避免这种状况:1. 使用同一个签名;2. 使用不一样包名
// 方法1 (签名配置方法能够Google)
android {
   buildTypes {
       debug {signingConfig signingConfigs.myConfig}
       release {signingConfig signingConfigs.myConfig}
   }
}
// 方法2 
android {
   buildTypes {
       debug {packageNameSuffix ".debug"}
   }
}
  1. Release版打包的apk文件名:经过下面的代码能够自动为生成的apk文件附加上版本和build日期,这里能够根据你的需求添加各类信息上去。
android {
    buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

            def today = new Date()
            if (variant.buildType.getName().equals("release")) {
                println "Change output apk name"
                variant.outputs.each { output ->
                    output.outputFile = new File(
                            output.outputFile.parent,
                            output.outputFile.name.replace(".apk", "-" + defaultConfig.versionName + "-" + today.format('yyyyMMdd') + ".apk"))
                }
            }
        }
    }
}

BuildVariants

Gradle的Android插件中有个BuildVariants的概念,其实简单来讲其实就是buildTypes+productFlavors,buildType前面咱们看到过了,主要就是debug和release的分别。而productFlavors就是咱们用来打包不一样版本app的主要方式。从字面意思来翻译指的就是不一样的“产品特色”。ui

Android Studio会自动根据build.gradle 生成对应的BuildVariants。好比如下代码:google

android {
    productFlavors {
        free {}
        paid {}
    }
}

会生成如下的BuildVariants:spa

pic

productFlavors的维度

productFlavors能够是多维的,听起来好像很难理解,这里举个栗子,有以下代码:插件

android {
    flavorDimensions("isfree", "channel")
    productFlavors {
        free {dimension "isfree"}
        paid {dimension "isfree"}

        googleplay {dimension "channel"}
        wandoujia {dimension "channel"}
    }
}

可以生成以下的BuildVariants:翻译

pic

这里咱们就能够看到,咱们有两个维度,一个是是否免费,另外一个是渠道,咱们可以生成2*2=4种Flavor,而且每一个Flavor都有debug和release,总共就有8种不一样的APK。因此理论上来讲经过组合Flavor,咱们能够作到各类不一样的分类。

接下来咱们来看看productFlavors能作什么? ### 定义渠道

在国外通常来讲开发者不太须要去管渠道的问题,他们的App只须要发往GooglePlay就能够了,可是在中国,咱们有众多的APK分发平台,咱们的APK须要发往各类地方,在作APP统计的时候咱们就须要在APK里写入一些特征变量,发送到统计平台,以区分不一样的渠道,在过去用ant打包的时代,咱们一般的作法就是用不一样的渠道名来重复ant任务一遍一遍地打包。

若是用gradle:咱们能够经过增长一个名为channel的dimension来给每个渠道一个特殊标示,代码就是咱们以前看到的。可是你可能会问,我怎么在统计的时候获取这个渠道名呢?其实很简单,Android Studio会为咱们生成一个名叫BuildConfig的类,这个类有一些关于打包的静态变量,下面是一个示例:

public final class BuildConfig {
  public static final boolean DEBUG = Boolean.parseBoolean("true");
  public static final String APPLICATION_ID = "me.zheteng.android.example";
  public static final String BUILD_TYPE = "debug";
  public static final String FLAVOR = "freeGoogleplay";
  public static final int VERSION_CODE = 1;
  public static final String VERSION_NAME = "1.0";
  public static final String FLAVOR_isfree = "free";
  public static final String FLAVOR_channel = "googleplay";
}

其实不止是渠道,经过这个类咱们还能够很方便地得到这个APK的各类信息。相信你们一眼就能看出来每一个字段的意思。(咱们甚至还能够自定义字段)。

若是渠道很是多,你也能够经过读配置文件的方式动态生成不一样的flavors。

若是我每一个flavor都有点特别呢?

有的时候咱们每一个flavor可能不仅是一个渠道名这么简单,个人ICON可能给每一个渠道的有所不一样,个人包名也可能有所不一样。全部这些,均可以直接在这个flavor中从新定义:

android {
    productFlavors {
        googleplay {
            applicationId "me.zheteng.android.example.googleplay"
        }
    }
}

若是须要不一样的源代码或资源文件,能够在app/src下新建一个名为“flavor名”的目录(这里就是googleplay)。也就是app/src/googleplay,而后这个目录下的结构和app/src/main中是同样的,打包的时候会优先使用当前flavor下的文件。

其余Gradle小技巧

Provider名称

咱们知道Provider的authority是系统中全局惟一的,有时候咱们要为不一样的flavor将authority改为不一样的,经过gradle你能够这样实现:

<provider
    android:exported="true"
    android:name="com.path.to.my.Provider"
    android:authorities="${applicationId}.provider"/>

你问我Java代码中怎么获取?难道你忘了BuildConfig了嘛?

Manifest 占位符

有些SDK会把配置在Manifest文件中的meta信息里,而不一样的flavor这个信息不同,这是咱们能够经过Manifest 占位符来实现:

<meta-data android:value="${UMENG_APPKEY}" android:name="UMENG_APPKEY"/>
android {
    productFlavors {
        googleplay {
            applicationId "me.zheteng.android.example.googleplay"
            manifestPlaceholders = [UMENG_APPKEY: "个人友盟KEY"]
        }
    }
}

总结

Gradle的灵活程度超乎想象,若是基本功能没法知足你,你还能够经过本身编写Groovy插件或者task来实现无穷的可能性,欢迎将你的思路分享出来~

相关文章
相关标签/搜索