4.构建变种版本

使用场景:
1.应用拥有付费版和免费版。2.应用需要为各个平台打包。3.其他需要产生不同版本的情况。

在AS中Gradle为我们默认创建了两个构建类型(build types),还有另外一个概念 product flavor,它能让我们更好的管理APP或library的各种版本。 Build types 和 product flavors 通常结合使用,他们统称build variant。
构建类型+定制产品=构建变种版本,BuildType + ProductFlavor 任何一种组合都会是一个版本。

章节主题:

  • Build types
  • Product flavors
  • Build variants
  • Signing configurations

一,Build types

在Gradle 的Android plugin中,一个build type用来定义APP或library如何构建。每个build type都能指定一些debug符号表,比如application ID,是否应该混淆,无用资源是否应该被删除等等。这些参数在可以在 buildTypes block中定义,在AS中一个标准的buildTypes block如下:

android {
buildTypes {
        release {
            minifyEnabled true
            shrinkResources true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

buildTypes block默认为我们生成了一个release版,minifyEnabled为true代表开启混淆,shrinkResources为true代表删除无用资源,proguardFiles 代表混淆规则文件名称,第一个是Android自带通用混淆规则,第二个是项目自定义混淆规则。混淆规则编写可以参考郭神的Android安全攻防战,反编译与混淆技术完全解析(下)

1.创建build types

当默认的配置不能满足需求时,我们也能很简单的在buildTypes block里面配置相应参数。如下一个创建staging的build type:

     android {
     buildTypes {
              staging {
                   applicationIdSuffix ".staging"
                   versionNameSuffix "-staging"
                   buildConfigField "String", "API_URL", "\"http://staging.example.com/api\""
                }
            }
        }

staging为 application ID添加了后缀,使staging的application ID和 debug,release版本不同。比如:
Debug: com.package
Release: com.package
Staging: com.package.staging
这样可以使你能在同一个设备上安装Staging和release版,staging版本也有version名后缀。buildConfigField 在第二章介绍过。
在定义一个新的build type时,也不需要从头定义,可以摘抄一些其他build type的属性, initWith()方法摘抄了debug type的属性,当定义了相同属性会覆盖。

android {
 buildTypes {
       staging.initWith(buildTypes.debug)
       staging {
            applicationIdSuffix ".staging"
            versionNameSuffix "-staging"
            debuggable = false
         }
     }
}

2.Source sets

当创建一个新的 build type时,Gradle也会创建一个新的source set,默认source set和build type名称相同,但是这个目录不会默认创建,需要自己去为build type创建source set目录。你可以通过source set 为特定版本添加自定义代码。
Resources在source set处理上有些特别,相同名称的Drawables 和layout files将覆盖main source set,但是
values 文件不会,Gradle将合并不同的地方。

main source set的 strings.xml文件
<resources>
 <string name="app_name">TypesAndFlavors</string>
 <string name="hello_world">Hello world!</string>
</resources>
 staging build type source set的 strings.xml文件
<resources>
 <string name="app_name">TypesAndFlavors STAGING</string>
</resources>
merged strings.xml file 
<resources>
 <string name="app_name">TypesAndFlavors STAGING</string>
 <string name="hello_world">Hello world!</string>
</resources>

3.Dependencies

每个build type都可以有它们自己的dependencies.例如在debug包里添加logging

dependencies {
 compile fileTree(dir: 'libs', include: ['*.jar'])
 compile 'com.android.support:appcompat-v7:22.2.0'
 debugCompile 'de.mindpipe.android:android-logging-log4j:1.0.3'
}

二,Product flavors

与build type相比,Product flavors适用于为同一APP创建不同版本,典型的就是付费和免费版。为不同平台生产不同版本。build type主要用于内部使用,如果是发布到平台上,而且想和已发布的版本区分开,就应该使用 product flavors 。

1.创建product flavors

方法和build types类似,productFlavor block。

android {
 productFlavors {
   red {
     applicationId 'com.gradleforandroid.red'
     versionCode 3
   }
 blue {
     applicationId 'com.gradleforandroid.blue'
     minSdkVersion 14
     versionCode 4
   }
 }
}

Product flavors和 build types拥有不同属性,因为product flavors是ProductFlavor class 的对象。defaultConfig 对象在build scripts中,product flavors会共享 defaultConfig的属性,所以可以在defaultConfig里配置product flavors的共同属性。每个flavor也会覆盖相同属性。

2.多flavor variants

android {
   flavorDimensions "color","price"
    productFlavors{
        red{
            flavorDimension "color"
        }
        blue{
            flavorDimension "color"
        }
        free{
            flavorDimension "price"
        }
        paid{
            flavorDimension "price"
        }
    }
}

例如上面,有付费版和免费版,颜色上面还有要求。要结合几种情况,首先指定flavorDimensions属性(在Android block中定义),然后分别在productFlavors block中指定版本,然后会产生以下几种版本(结合build types)。

  • blueFreeDebug and blueFreeRelease
  • bluePaidDebug and bluePaidRelease
  • redFreeDebug and redFreeRelease
  • redPaidDebug and redPaidRelease

每个flavor都必须指定一个flavorDimension属性, flavorDimensions 定义的属性必须使用,顺序也很重要,当两个类型结合时,相同属性会被前面的覆盖,例如color覆盖price的属性。产生版本个数为:

总数=color属性个数 * price熟悉个数 * build type个数(debug+release)

三,Build variants

Build variants是build types和product flavors结合的产物,在AS左侧有Build Variants窗口可以查看各个版本,单击即可构建该版本。如果没有指定 product flavors,Gradle的Android插件会默认生成debug和release build type。

Build Variants.png

1.Tasks

Android plugin for Gradle会为每个build variant创建task。例如assembleDebug会构建所有debug版本,assembleBlue会构建所有blue版本。


tasks.png

2.Source sets

和 build type一样,Build variants也拥有自己的source set,例如blue flavor 和free flavor的目录,src/blueFreeDebug/java/,也可以使用sourceSets block指定目录路径。

3.Resource and manifest合并

在打包前Gradle会合并 main source set 和 build type source sets资源,library的资源也会被合并。当在debug版本时想保存log文件,需要一些文件读写权限,但在正式版时不需要此权限,可以在debug 的source set里面申请额外的权限。
resources and manifests的优先级顺序:

优先级顺序.png

在main source set和一个flavor中存在一个相同的resource时,打包flavor时会使用flavor resource,而不是main source set。library的resource优先级最低。

4.Creating build variants

android {
   buildTypes {
   debug {
     buildConfigField "String", "API_URL",
     "\"http://test.example.com/api\""
   }
   staging.initWith(android.buildTypes.debug)
   staging {
      buildConfigField "String", "API_URL",
      "\"http://staging.example.com/api\""
     applicationIdSuffix ".staging"
     }
   }
  productFlavors {
   red {
     applicationId "com.gradleforandroid.red"
     resValue "color", "flavor_color", "#ff0000"
     }
   blue {
     applicationId "com.gradleforandroid.blue"
     resValue "color", "flavor_color", "#0000ff"
     }
   }
}

如上定义,会产生build variants: blueDebug, blueStaging, redDebug, 和redStaging

blueDebug.png

staging build type 的 source set的drawable目录下app icon和debug不同


redStaging.png

5.Variant filters

有时需要过滤掉一些Variant 来加快assemble 命令。(assemble 构建所有Variant )

//过滤掉release下的blue版本,这个task也被取消了。看得懂也行,反正我也写不来(ง ˙o˙)ว
android.variantFilter { variant ->
    if(variant.buildType.name.equals('release')) {
        variant.getFlavors().each() { flavor ->
            if (flavor.name.equals('blue')) {
                variant.setIgnore(true);
            }
        }
    }
}

四,Signing configurations

发布APK时需要签名

android {
  signingConfigs {
        release {
            //签名文件路径
            storeFile file("release.keystore")
            //签名文件的密码
            storePassword "secretpassword"
            //指定签名文件的别名
            keyAlias "gradleforandroid"
            //指定签名文件的别名配对密码
            keyPassword "secretpassword"
        }
    }
   buildTypes {
        release {
            //指点签名配置
            signingConfig signingConfigs.release
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,287评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,346评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,277评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,132评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,147评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,106评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,019评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,862评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,301评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,521评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,682评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,405评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,996评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,651评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,803评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,674评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,563评论 2 352

推荐阅读更多精彩内容

  • 开发应用时, 通常会有几个不同的版本。最常见的是有一个测试用的临时版本和一个生产版本。这些版本通常有不同的设置,比...
    sollian阅读 2,368评论 0 2
  • 当你在开发一个app,通常你会有几个版本。大多数情况是你需要一个开发版本,用来测试app和弄清它的质量,然后还需要...
    justCode_阅读 427评论 0 2
  • 第四篇( 构建变体 ) 当你在开发一个app,通常你会有几个版本。大多数情况是你需要一个开发版本,用来测试app和...
    一剑飞鸿阅读 674评论 0 0
  • 当你在开发一个app,通常你会有几个版本。大多数情况是你需要一个开发版本,用来测试app和弄清它的质量,然后还需要...
    雪残阅读 408评论 0 0
  • 转载注明出处:http://www.jianshu.com/p/5255b100930e 0. 前言 完全由个人翻...
    王三的猫阿德阅读 2,511评论 0 4