如何使用Gradleapp构建版本正在处理不同版本的app

谈谈Android开发中的Gradle那些事之不同BuildType编译出不同版本号的apk - 简书
谈谈Android开发中的Gradle那些事之不同BuildType编译出不同版本号的apk
今天我们要来谈谈 如何让不同的BuildType编译出不同的版本号
没搞错吧?
这有什么用??
为什么会有这样的需求???
不想当产品的QA不是一个好RD
RD不只是PM的RD, QA也总能在非常时期提出一些非常独(坑)特(爹)的需求,而我们只能说没问题!(: 男人怎么能说自己不行)
废话不多说,正式进入今天的主题:
为什么要编译出不同的版本号呢?相信大部分公司为了更好的统计、分析app线上crash率等,都会用到一些第三方crash统计,这里拿Fabric举例Fabric 只能根据app的versionCode值(也就是最终写到manifest文件中的versionCode值)来区分app版本。这里我为什么说最终呢,别着急,耐心看下去。
此时,我们的最(罪 )佳(魁)P(祸)M(首) QA发话了..
那个 ...考虑到QA在测试的过程中会遇到一些难以复现的crash等,我们需要在测试环境下也统计crash信息且 ...要和线上的区分开来
于是我们的故事就从这里开始了......
如果说要根据不同的Flavor编译出不同的版本号,那太easy了(这里我们的versionCode是根据versionName按规则转换而来的,转换规则不足3位前面补0: 这里versionName 1.2.1)
productFlavors {
// 测试环境的包
versionCode 121
versionCode 1002001
O啦,是不是很简单。那么问题来了,这样的话就得依赖flavor。而事实上我们往往通过flavor来作为渠道的区分。那这么一来就会引起冲突:我们既要产生多渠道,又要编译出不同的VersionCode.
排除上述方式,我的天啊。杀了我吧,搞不了!别怕。世上无难事,只怕有心人。在这里我首先要感谢强大的互联网,还要感谢人民,以及背后所有默默支持我的朝阳群众。经过不屑的努力,终于被我们发现了,快到碗里来。
首先在主module下的build.gradle中定义一个方法 getAppVersionCode
def getAppVersionCode(shortVersionCode) {
String versionName = rootProject.ext.android.versionName
String code = ""
if (shortVersionCode) {
code = versionName.replaceAll("\\.", "")
String[] version = versionName.split("\\.");
version.each {
while (it.length() & 3) {
it = "0" +
println code
return Integer.valueOf(code)
这里我们先说一下rootProject.ext.android.versionName通常我们为了更好的管理Android版本信息、常用依赖等,我们将这些基础配置写到一个单独的gradle文件中作为全局配置。配置ext,然后在我们的工程根目录下的build.gradle文件中做如下配置。这样就可以在全局gradle中访问ext中的信息了。
apply from: 'config.gradle'
// 统一配置support包版本
supportLibraryVersion
= '23.1.1'
android = [compileSdkVersion
buildToolsVersion
: "23.0.3",
minSdkVersion
targetSdkVersion
versionName
: "1.3.1",
renderscriptTargetApi: 19,]
细心的同学可能会发现这里只定义了VersionName,而没有定义VersionCode。为什么呢?山人自有妙用!
好好说话因为我们的VersionName是不变的,而VersionCode要根据环境,然后通过调用上面定义的getAppVersionCode去赋值听到这里是不是有思路了。
别想了,你知道在哪里赋值吗?
好了,回归正题。如果你对gradle语法还不是很清楚,可以看看这篇文章
getAppVersionCode方法就是用来根据VersionName生成versionCode值,这里接收 一个参数,长位还是短位的来得到我们需要的
方法定义好了,该怎么用呢?注意了,注意了,重要的事情说三遍:大招来了!!!大招来了!!!大招来了!!!
applicationVariants.all { variant -&
variant.outputs.each { output -&
// 获取渠道
def flavor = variant.productFlavors[0]
def flavorName
if (flavor == null) {
flavorName = "defaultName"
flavorName = flavor.name
def outputFile = output.outputFile
def fileName
if (outputFile != null && outputFile.name.endsWith('.apk')) {
def isRelease = variant.buildType.name.contains('release');
// 非release为3位code,用于区分fabric线上和dev
// variant.mergedFlavor.versionCode 表示修改打包时versionCode的值
variant.mergedFlavor.versionCode = getAppVersionCode(!isRelease)
fileName =
"${flavorName}-${variant.buildType.name}-v${variant.versionName}(${variant.versionCode}).apk";
println fileName
output.outputFile = new File(outputFile.parent, fileName)
最关键的一步,你有看到吗。
variant.mergedFlavor.versionCode = getAppVersionCode(!isRelease)
没错,就是这里。我们在自定义编译后的apk重命名的同时,遍历我们的输出文件,读取apk,然后访问variant的buildtype判断是release,就设置versoncode为长位的,否则为短位的。
啊?这么简单?
没错就是这么简单。
这里我们简单的说一下 Variant
Variant就是Build Variant,中文含义 “构建变种版本”
Build Variant = Build Type + Product Flavor构建变种版本= 构建类型+定制产品
我们可以通过Variant访问到productFlavors,buildType,从而可以更改我们想要更改的任意两者的相关配置
好吧,就到这里了。就问你是不是很简单?
哎呀,还要多说一句。第一次写分享,如果你觉得对你还有点用,希望大大支持。哦啦。使用IDE创建Gradle web project - Wonderful Days - ITeye博客
博客分类:
0.前提必须保证你的IDE安装了Gradle插件
1.右键选择New-other,通过过滤器找到Gradle项目,点击Next
2.输入项目名称,选择一个模板
3.添加一个名称为webapp的sourcefolder
4.右击你的项目,选择Project Facets-&Convert to faceted form...-&apply
5.勾选Dynamic Web Module,注意下方的滚动条,向右拖动选择版本,点击下方的Further configuration available
6.输入src/main/webapp,并勾选Generate web.xml deployment descriptor
好了,去吧 泰罗,勇敢的创建一个index.jsp 敲上你的Hello world.
更多欢迎访问Gradle群组
浏览: 212967 次
来自: 北京
夜行侠老师gradle教学视频地址:http://www.it ...
gradle init --type pom
Gradle 2.0以上,需要把Compile改为JavaCo ...
默认情况下都报错 没有setupBuild这个task 楼主提 ...
感谢提供,确实是这样的……posts - 25,&
comments - 3,&
trackbacks - 0
欢迎转载,但请保留文章原始出处&_&&
生命壹号:
1、gradle的概念
2、gradle配置jar包,和libs文件夹导入jar包的区别
3、签名打包:
&&& (1)Studio
&&& (2)命令行
&&& (3)gradle wrapper的原理
4、BuildConfig的使用
5、简单介绍module中build.gradle文件参数含义
一、gradle的概念:
gradle是一个构建工具
gradle是以Groovy语言为基础的
gradle主要面向的是Java语言
打开Android Studio内置的终端,在输入如下命令查看gradle版本:
gradlew -v
如果是第一次运行这个命令,系统会帮我们下载gradle到本地,下载到的路径是:
输入上述命令后,查看到gradle的版本2.2.1,如下图所示:
二、通过gradle来导入jar包:
我们在上一篇文章中第二段的第3小节中讲到了通过拷贝文件到libs文件夹来导入jar包。这次来讲一下怎么通过gradle来配置jar包。我们还是以谷歌的gjson.jar为例,如果之前已经通过拷贝文件方式倒入过了,请先自行删掉。
1、通过gradle配置第三方jar包
我们看到,每个module都有一个build.gradle文件,它其实是对应module的配置文件。关于build.gradle文件中具体内容的含义,我们将在最后一段进行讲解。
我们先来看一下名为app的这个module,它的build.gradle对应的图形界面其实是下面这个Project Stucture:
上图中,切换到dependencies标签下,如下图所示:
上图中,点击添加,然后选择"Library dependency",弹出如下界面:
上图中,我们在搜索框中输入&gson&,然后确定,就弹出了箭头处的我们需要的jar包,添加它即可:
之后我们会发现,app这个module的build.gradle中多了一行代码,表示引入了gson.jar:
其实,如果你能记得住上方这行代码,直接写出代码来也是可以导入的。
此时,gson这个jar包不再是出现在libs这个文件夹下了,而是出现在最下方的External Libraries中,如下图所示:(而且是最新版本哦)
2、gradle导入jar包的特点:(和libs文件夹导入jar包的区别)
gradle导入jar包更方便,一行代码即可搞定。不像后者那样还要自己去官方下载。
如果官方将jar包更新了,我们只需要在build.gradle中改一下版本号就行了,不用重新去官网下载。
3、通过gradle导入的jar包是从哪里来的:
需要注意的是:不是所有的jar包都是可以通过gradle来导入的。那通过gradle导入的jar包是从哪里来的呢?解释如下:
我们发现HelloWorld这个project的目录下有一个build.gradle文件,打开它:
上图中第17行的"jcenter()"的意思是,所有通过gradle导入的jar包都是从这个中央仓库上扒下来的。如果你需要的jar包在这个网站上没有,那就无法通过gradle的方式来导入哦。
顺便提一下,上图中第8行的classpath中的gradle 1.1.0是android的一个gradle插件(也是从中央仓库扒下来的)。而我们自己使用的gradle版本如下图所示:
我们自己下载好的gradle的路径如下:
三、签名打包的两种方式:
注:给我们自己开发的app签名,就代表着我自己的版权,以后要进行升级,也必须要使用相同的签名才行。签名就代表着自己的身份(即keystore),多个app可以使用同一个签名。
如果不知道签名是啥意思,请自行百度哦。在eclipse中签名的方法是:选中工程,邮件选择"export-android-export android application",
1、方式1:通过Android Studio进行签名:
选中app这个module,选择菜单栏"Build-Generate signed apk":
弹出如下界面:
上图中,如果你是第一次使用签名,就单击红框部分创建一个新的签名;如果你之前有过签名的文件,就选择蓝框部分进行导入即可。那我就先选择红框部分吧:
上图中,点击"finish"之后,可以看到Android Studio的最下方显示:Gradle正在执行assembleRelease这样一个任务,如下图所示:
生成签名好的apk之后,会弹出提示:
2、方式2:通过命令行的方式进行签名:
(1)加载Key Store:
我们先删掉上面的通过第一种方式所签名的apk文件。接下来进行第二种方式来签名,即命令行的方式。
打开Project Stucture图形化界面:
上图中,选中app这个module,然后切换到singning标签栏,紧接着点击添加,然后生成release签名信息,紧接着点击"OK"。接着做如下操作:
上图中,切换到Build Types标签,将Signing config选择为"release",即将刚刚生成的release签名信息配置进去。
操作完成之后,我们可以看到app这个module的build.gradle文件多出了如下红框部分的代码:
然后执行菜单栏的"build-clean Project":
(2)生成realease版本的apk:
紧接着在命令行Terminal输入如下命令:(AS已经将命令行Terminal集成到了软件当中)
gradlew assembleRelease
如果运行成功,效果如下:
生成的签名好的apk在如下位置:
3、为什么要使用gradlew命令而不是gradle命令:
在HelloWorld工程目录下有一个gradle文件夹,在gradle/wrapper目录下有一个gradle-wrapper.properties文件,打开它:
上图代表着HelloWorld这个工程所依赖的gradle的版本信息。上图的红线表示,如果我们的工程中没有gradle,软件会根据这个url去下载gradle,终于知道为啥第一次打开AS时会这么慢了吧?
如果我们执行了gradlew命令,实际上是执行上面的gradle wrapper,然后找到我们已经下载好的gradle 2.2.1。如果现在有很多个工程,但是每个工程的gradle版本都不一样,我就必须要将每个版本的gradle都要配置到环境变量当中,而执行了gradlew命令,就会避免这个麻烦。
四、BuildConfig文件:
BuildConfig是IDE自动生成的一个类,在elipse中即存放在gen目录下(如R文件)。而在Adroid Studio中,BuildConfig文件存放的位置是:app/build/generated/source/buildconfig/dubug/&packagename&/BuildConfig.java中。如下图所示:
五、module中build.gradle文件参数含义:
主要是module的build.gradle,截图如下:
01行:apply plugin: 'com.android.application'&&& 表示该module是这个应用程序的module
15行:applicationId "com.smyhvae.helloworld"&&& 应用程序的包名
16、17行:向下兼容的最小版本、编译版本。&&& 注:在app/src/main/AndroidManifest.xml中不再出现这个信息了。
23行:需不需要利用24行的proguard文件来混淆代码。在release状态下,最好改为true。
阅读(...) 评论()关注社区微信公众号: PMvideo
Gradle使用技巧总结
记录使用Android Studio以及Gradle的心路历程。系列文章将持续更新中。。。
第一次加载项目缓慢
对于初用Android Studio的朋友来说,项目构建是一个很缓慢的过程,因为中间会下载好多好多东西。这里我仅总结下如何提升编译过程中的下载组件部分,其他什么daemon或是configureondemand我在使用时候发现几乎没有什么效果。我以为例,先看看它的目录结构
lottie-android
(1) 确定根目录下的build.gradle中Android Gradle Plugin版本是否与本地插件版本一直,若不一直修改为本地插件版本
Android Gradle Plugin插件版本
这里是2.3.0-beta3,我本地是2.2.3,直接修改成我本地的版本号即可(2) 确定gradle/wrapper/gradle-wrapper.properties文件中gradle的版本在C:\Users\用户名\.gradle\wrapper\dists是否已经离线存在
gradle的版本
这里是3.3,我本地是2.14.1,直接修改成我本地的版本号即可(3) 分别查看各个module中的build.gradle里面compileSdkVersion、buildToolsVersion、com.android.support等Android SDK的相应版本是否已经存在。(4) 如果存在其他第三方库,若能提前下载完成最好。已经下载完成的库存放在C:\Users\用户名\.gradle\caches\modules-2\files-2.1里面
第三方库存放路径
以fresco为例,如果你之前在其他电脑上找到相应完整的目录,请拷贝到其中,以节省下载所需时间(5) 明确版本号写法的差别。先看下这几种写法,以gson为例
dependencies {
compile 'com.google.code.gson:gson:2.2.1'
compile 'com.google.code.gson:gson:2.2.+'
compile 'com.google.code.gson:gson:2.+'
compile 'com.google.code.gson:gson:+'
大家大概心里有数了吧,版本号模糊,就意味着每次都要去对比同步得到最新版本,时间就花费在这个上面了,所以我们的版本号一定要写精确,这样才能节省这些时间
基础配置篇
设置全局编译器的版本
在使用retrolambda的时候有过对java编译器的配置如果仅需某一个module单独支持,只要在相应module的build.gradle下进行配置即可
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
如果你希望全局配置,则需要配置根目录下的build.gradle,在其allprojects中进行配置即可
allprojects {
repositories {
tasks.withType(JavaCompile) {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
注意设置java1.8版本需要开启jack编译,否则会抛出Error:Jack is required to support java 8 language features
defaultConfig {
jackOptions {
enabled true
签名文件的存放与配置
在你的工程里,是不是这样对签名进行如下配置?
signingConfigs {
storeFile file("android.keystore")
storePassword "abcd1234"
keyAlias "android.keystore"
keyPassword "abcd1234"
这种看上去很直观,但是不好的地方就是安全性不够格。我们可以将这些高危参数放到专门的配置文件中,并且在提交代码的时候将其从版本管理中忽略。我们将配置信息写在gradle.properties中
# keystore配置信息
storeFile_=android.keystore
storePassword_=abcd1234
keyAlias_=android.keystore
keyPassword_=abcd1234
必要信息写完之后,即可修改build.gradle中的signingConfigs,直接引用gradle.properties中的配置信息
storeFile file(storeFile_)
storePassword storePassword_
keyAlias keyAlias_
keyPassword keyPassword_
如果签名信息没有放到gradle.properties或者local.properties里,那就需要自己通过代码来读取配置信息,从而获取相应的数值。注意文件路径的选择,这里示例还是gradle.properties文件
// 加载签名配置文件
Properties props = new Properties()
props.load(new FileInputStream(file("../gradle.properties")))
signingConfigs {
storeFile file(props['storeFile_'])
storePassword props['storePassword_']
keyAlias props['keyAlias_']
keyPassword props['keyPassword_']
占位符的使用
占位符常用在androidManifest.xml中,随后可在相应module的build.gradle中将其进行赋值。这个大多用在多渠道打包设置渠道名称上先看下manifest文件,以友盟多渠道举例说明,这里的占位符就是UMENG_CHANNEL
&application
.............
&meta-data android:value="${UMENG_CHANNEL}" android:name="UMENG_CHANNEL"/&
.............
&/application&
我在defaultConfig下配置manifestPlaceholders,这里将UMENG_CHANNEL的值设置为“测试渠道”
manifestPlaceholders = [UMENG_CHANNEL : "测试渠道"]
最后使用代码验证一下
ApplicationInfo info=getPackageManager().getApplicationInfo(getPackageName(), PackageManager.GET_META_DATA);
Log.d("MainActivity", info.metaData.getString("UMENG_CHANNEL"));
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
同样的配置也可以在productFlavors上,这个就是多渠道打包中统计渠道来源的常规方法
productFlavors {
version1 {
manifestPlaceholders = [UMENG_CHANNEL : "version1"]
version2 {
manifestPlaceholders = [UMENG_CHANNEL : "version2"]
设置第三方远程仓库
如果我们的项目不在center或者MavenCenter的话,我们就需要单独配置maven信息了,因为我目前没有尝试搭建过maven仓库,所以在github截图来展示。关于本地Maven的操作,请参考
如果仓库在本地的话,相应url换成本地地址即可。我一般使用的是jitpack这个远程仓库,他可以直接与github进行关联,从而生成相应的版本信息。关于jitpack的使用请参考
allprojects {
repositories {
maven { url 'https://jitpack.io' }
构建参数篇
多编译环境设置
这个就涉及到buildTypes了。在默认情况下,buildTypes可以让gradle插件自动构建一个release版本app以及一个debug版本app。这两个版本区别主要在app配置以及签名上。debug包使用默认签名信息,这个签名文件在/.android/debug.keystore,而release包需要你稍后自行配置。如果你需要创建其他的build type,你可以在buildTypes这个DSL下进行配置。这里我给出一个简单的buildTypes配置范例
signingConfigs {
storeFile file("android.keystore")
storePassword "abcd1234"
keyAlias "android.keystore"
keyPassword "abcd1234"
} catch (ex) {
throw new InvalidUserDataException(ex.toString())
buildTypes {
applicationIdSuffix '.debug'
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.release
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
shrinkResources false
zipAlignEnabled true
// 如果我们想要新增加一个buildType,又想要新的buildType继承之前配置好的参数,init.with()就很适合你了
hiapk.initWith(buildTypes.debug)
applicationIdSuffix '.hi'
versionNameSuffix '.hi'
如此配置之后,Build Variants模块如图所示,可以得到3个不同打包配置的apk文件
buildTypes在debug包里,applicationId后缀为.debug;release包中的signingConfig文件为signingConfigs下的release;最后还有一个自己添加的buildType--hiapk,他的配置复制于debug,同时修改了applicationId后缀与versionName后缀我们可以使用gradle build命令进行全部打包,也同样可以使用gradle assembleHiapk这种单一打包方式进行打包。打包完成之后我们反编译一下来看看三个apk的manifest信息
可以很清楚的看出来其中的不同这里还有其他的DSL简单介绍一下signingConfigs:秘钥配置信息。shrinkResources:是否清理无用资源文件,注意如果选择true,那么minifyEnabled也得为true才行,即开启混淆zipAlignEnabled:是否开启zipAlign压缩
编译项目时设置可引用参数
在刚才的buildTypes中有一个重要的DSL——buildConfigField,在打包编译项目时可以直接设置一些作用于项目的参数,从而在项目中使用这些参数进行逻辑层处理。buildConfigField支持Java中基本数据类型,如果是字符串,记得转义后加双引号这里我们定义一个字符串,名称叫SERVER_HOST
buildConfigField "String", "SERVER_HOST", "\"http://200.200.200.50/\""
设置完之后编译项目,在BuildConfig.java中可以查到之前配置的相关信息
BuildConfig.java
使用时候这样
Log.d("MainActivity", BuildConfig.SERVER_HOST);
查看控制台输出
buildconfigs
玩转依赖篇
说到依赖,一般情况下我们只需要将compile远程仓库地址拷贝一下就行了,其实依赖的学问很大,远远不是compile一下而已。
Compile: 默认配置,该依赖会参与编译并且打包到所有的build type以及flavors的apk中Provided: 对所有的build type以及flavors来说只在编译时使用,只参与编译并不打包到最终apkAPK: 只会打包到apk文件中而不参与编译,所以不能在代码中直接调用jar中的类或方法,否则在编译时会报错另外三种compile只跟测试有关Test compile: 仅仅是针对单元测试代码编译以及最终打包测试apk时有效,而对正常的debug或者release apk包不起作用。Debug compile: 仅仅针对debug模式的编译和最终的debug打包时有效。Release compile: 仅仅针对release模式的编译和最终的release打包时有效。
依赖远程文件
这是最基本的用法,在上文也提及过了
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
依赖本地文件
当前模块下libs文件夹下的全部jar文件
compile fileTree(include: ['*.jar'], dir: 'libs')
指定路径下的全部jar文件
compile fileTree(dir: '../librarymodule/libs', include: '*.jar')
加载aar文件
repositories {
dirs 'libs'
这意味着系统将在libs目录下搜索依赖。同样的如果你愿意的话可以加入多个目录。这里系统直接加载libs文件夹下的aar文件
compile(name: 'aar的名字(不用加后缀)', ext: 'aar')
依赖本地库工程
compile project(':librarymodule')
冲突的解决方法
先来看看几种不同的写法对库的加载有何区别
// 下载包含该库在内的其他所依赖的所有库
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
// 只下载该库,其他所依赖的所有库不下载
compile 'io.reactivex.rxjava2:rxandroid:2.0.1@aar'
// 在使用@aar的前提下还能下载其他依赖库,则需要添加transitive=true的条件
compile ("io.reactivex.rxjava2:rxandroid::2.0.1@aar") {
transitive=true
// 去除某一个依赖库
compile ("io.reactivex.rxjava2:rxandroid:$rootProject.ext.rxandroid") {
transitive=true
exclude group: 'io.reactivex.rxjava2', module: 'rxjava'
这时候,我又加了一个rxbinding库,这时候依赖树是这样的结构
依赖树结构
如果我想将项目中的所有rxjava2引用都去除,可以用configurations实现
configurations {
all*.exclude group: 'io.reactivex.rxjava2', module: 'rxjava'
configurations {
compile.exclude module: 'rxjava'
如果在configuration中定义一个exclude,那么所有单独设置的transitive dependency都会被去除。你可以只指定group的名字, 或只指定module的名字,或二者都指定
configurations
明白如上写法造成的区别之后,你应该就知道如何解决包冲突了吧这里对gradle dependencies中的-&、 (*)进行解释固定版本: 唯一的依赖固定版本(*):还存在该库其他版本的依赖或者间接依赖,并且默认选择(*)所标注的版本。这里rxjava版本就是使用rxbinding里的2.0.2版本1-&版本2(*):还存在该库其他版本的依赖或者间接依赖,并且并且选择版本2。这里rxandroid版本就是使用2.0.1configurations DSL还可以通过Force强制约束某个库的版本,比如我这里将appcompat-v7包限定为25.1.0
configurations.all {
resolutionStrategy {
force "com.android.support:appcompat-v7:25.1.0"
按构建目标定制依赖库
如果你想给productFlavors中的version2添加相应的依赖,只需要在它的名称后面加上Compile这样配置即可
version2Compile 'com.github.AlphaBoom:ClassifyView:0.5.2'
外部配置依赖版本
当我们直接建立完项目之后,android的相关配置就已经自动完成了,像这样
默认gradle配置
其实这样也算相对清爽吧,但是一旦引用库数量变多,这样或许就不够直观了。这种情况下,我们最好有一个单独的文件去统计这些配置。我们新建一个config.gradle作为配置文件
config.gradle
具体配置如下
androidGradleVersion = '2.3.1'
AndroidSupportVersion = '25.3.1'
AndroidConstraintLayoutVerson = '1.0.2'
compileSdkVersion = 25
buildToolsVersion = '25.0.2'
defaultConfig = [
applicationId : "com.renyu.gradledemo",
minSdkVersion : 15,
targetSdkVersion : 25,
versionCode : 1,
versionName : "1.0"
其中defaultConfig是一个map键值对,有别于上方的公共配置,这样看起来更清晰简洁这里我们需要使用apply from来引用config.gradle。同理当你的gradle脚本太大的时候,你可以按照具体任务类型将一个大gradle脚本拆分成几个子脚本,然后分别apply from引入到主脚本中。
// 这里的apply是为了让子模块使用
apply from: "config.gradle"
buildscript {
repositories {
dependencies {
// root下build.gradle使用
apply from: "config.gradle"
classpath "com.android.tools.build:gradle:$androidGradleVersion"
// NOTE: Do not place your applicati they belong
// in the individual module build.gradle files
allprojects {
repositories {
task clean(type: Delete) {
delete rootProject.buildDir
再看看app模块下的build.gradle的配置
apply plugin: 'com.android.application'
compileSdkVersion pileSdkVersion
buildToolsVersion rootProject.ext.buildToolsVersion
defaultConfig {
applicationId rootProject.ext.defaultConfig.applicationId
minSdkVersion rootProject.ext.defaultConfig.minSdkVersion
targetSdkVersion rootProject.ext.defaultConfig.targetSdkVersion
versionCode rootProject.ext.defaultConfig.versionCode
versionName rootProject.ext.defaultConfig.versionName
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
buildTypes {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
compile "com.android.support:appcompat-v7:$rootProject.ext.AndroidSupportVersion"
compile "com.android.support.constraint:constraint-layout:$rootProject.ext.AndroidConstraintLayoutVerson"
testCompile 'junit:junit:4.12'
注意这里单引号与双引号的区别,对于字符串你既可以使用单引号或者双引号,但是字符串可以插入表达式
对layout进行模块化分包
一般情况下我们app的布局文件会随着项目的开发而发生爆炸式的增长
一般项目layout下文件列表
这种组织结构会让人眼花缭乱不知所措,时间久了就会忘记某个功能用的都是哪些布局文件了。今儿就来向大家介绍如何对layout进行模块化分包。首先来看看效果
对layout进行模块化分包
怎么样,main模块与main2模块他们的布局是相互独立保存的,没有堆叠在一起。那么这个是怎么做到的呢?之前大家从eclipse直接转项目到Android Studio上的时候,不知道有没有注意到在app模块下的build.gradle有一个DSL叫sourceSets,通过修改sourceSets中的属性,可以指定哪些源文件(或文件夹下的源文件)要被编译,哪些源文件要被排除。Gradle就是通过它实现项目的布局定义。Android Studio插件默认实现了两个sourceSet:main和test。每个sourceSet都提供了一系列的属性,通过修改这些属性,可以定义该sourceSet所包含的源文件,比如java.srcDirs,res.srcDirs
sourceSets {
了解完原理之后那就看看怎么搞吧
按照自己的项目需求建立layout目录,例如本文就是/alllayouts/main/layout与/alllayouts/main2/layout
在module对应的build.gradle下添加sourceSets配置sourceSets {
res.srcDirs = [
'src/main/res/alllayouts/main',
'src/main/res/alllayouts/main2',
'src/main/res'
} 注意:最后一行要添加
多渠道多版本打包调试
之前在使用buildTypes的时候,我们提到过使用buildConfigField完成相应的参数初始化,这里还有一个更高级的功能,就是使用productFlavors来修改每个版本的不同部分,或者通过判断当前所使用的app是哪个版本,执行对应版本的代码。还是先简单看下结构
productFlavors结构
然后开始build.gradle的相关配置
productFlavors {
version1 {
version2 {
sourceSets {
java.srcDirs = ['src/main/java']
version1.java.srcDirs = ['src/version1/java']
version2.java.srcDirs = ['src/version2/java']
VersionInfo同时在version1与version2包里进行定义,区别仅仅在变量的值上。在sourceSets对差异部分进行配置,注意一下路径。
public class VersionInfo {
String v="2";
public class VersionInfo {
String v="1";
最后我们进行编译打包
编译完成后的结果
反编译查看两个包中的文件
这样即完成加载不同的类对象这里还有一个补充,如果你想修改不同渠道包的包名等信息,你可以直接在productFlavors下进行配置。applicationId这个DSL用于修改它们的applicationId,resValue支持res/values下的资源定义,与之前的buildConfigField区别是字符串无需加转义后的双引号。这里是app_name,所以app的应用名称也会被修改
productFlavors {
version1 {
applicationId "com.renyu.gradledemo.v1"
resValue "string", "app_name", "版本1"
version2 {
applicationId "com.renyu.gradledemo.v2"
resValue "string", "app_name", "版本2"
abiFilters可以优先适配需要适配的cpu,其他做兼容处理。如本例我们放置了armeabi、armeabi-v7a、x86三种类型CPU的so,其他的就让手机自己去做兼容处理去了
//选择要添加的对应cpu类型的.so库。
abiFilters 'armeabi', 'armeabi-v7a', 'x86' // 还可以添加 'armeabi-v8a', 'x86_64', 'mips', 'mips64'
莫名的抽风
之前在使用听云进行监控的时候,遇到一个很尴尬的事情:我仅仅在其中一个项目里面部署了听云,为什么在其他项目里面会出现听云的类找不到的错误呢?
java.lang.NoClassDefFoundError: com.networkbench.agent.impl.instrumentation
这时候无论你将全部听云配置都删除或是在.gradle里面将听云引用删除,都无法解决这个问题,这个就是android studio缓存的问题。那么怎么才能清理缓存呢?其实很简单,看图,在"file"菜单下有一个"Invalidate Caches / Restart",只要重启这个就行了
Invalidate Caches / Restart
笔记社区是一个面向中高端IT开发者、程序员的知识共享社区,通过网络抓取与文章分类总结,由专家为用户提供高质量的专题文章系列。
原文链接:/p/5be222e98efc
声明:所有文章资源均从网络抓取,如果侵犯到您的著作权,请联系删除文章。联系方式请关注微信公众号PMvideo【锤子视频-程序员喜欢的短视频】,笔记社区开发者交流群 。
今日签到3人
关注微信公众号:PMvideo

我要回帖

更多关于 app构建版本 的文章

 

随机推荐