前言
本文主要介绍了关于Gradle配置的相关知识,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧。
参考链接:https://developer.android.com/studio/build/index.html
本片文章的内容全部参考自上面的链接,其中有些内容是直接翻译的,有些内容是结合自己的经验总结的,可能有理解错误的地方,非常希望大家能指正出来,在交流中进步。
Gradle 编译过程
编译流程图
上图展示了一个典型的 App 编译过程,主要分为以几步:
自定义编译配置
Android Studio 的 gradle 插件方便我们在以下几个方面配置我们的编译选项:
Build Types - 编译类型
编译类型,包括我们最熟悉的 release 和 debug 两种类型,我们可以根据这两种类型定义出更多的类型。配置对应的 build.gradle 文件在 moudle 下,需要添加新的或者修改 Build Type ,只需要在 android{ ... }里面操作。
一个示例如下:
android { ... defaultConfig {...} buildTypes { release { //开启混淆 minifyEnabled true //混淆规则文件 proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } debug { //apk的后缀 applicationIdSuffix ".debug" } //debug的一个扩展 jnidebug { // 复制debug的属性和签名配置 initWith debug applicationIdSuffix ".jnidebug" //开启Jni调试 jniDebuggable true } } }
其中 initWith 可以方便我们继承其他的配置,只需要添加需要的部分。
Product Flavors - 构建不同版本
配置 apk 的版本信息,可以为每一个版本指定不同的 applicationId 和版本名称。关于 applicationId ,可以把它也理解为包名,不过和 Manifest 文件中的包名作用不同,它是用来给应用商店和设备区分不同的 app ,而 Manifest 中的 pakage 属性用来在源代码中引用 R 类和其他类。即同一份代码 applicationId 可以让它变成不同的 app 。
示例配置如下:
android { ... defaultConfig {...} buildTypes {...} productFlavors { demo { applicationId "com.example.myapp.demo" versionName "1.0-demo" } full { applicationId "com.example.myapp.full" versionName "1.0-full" } } }
通过上面的配置之后,如果 buildTypes 里面配置了两个编译类型,假如是 debug 和 release ,将会产生四个 apk 文件,每一种 buildType 都会和每种 flavor 进行组合拼接,进而产生不同的变种版本(Build Variant),上面对应的四个不同的变种版本分别是:demoDebug、demoRelease、fullDebug、fullRelease。
Mutiple Manifest Files - 合并多个清单文件
配置多个 Manifest 文件。经常会在项目中依赖其他项目,这个时候就会有多个 Manifest 文件,那在编译的时候该如何处理呢?这个时候需要进行合并,而且还必须有一套相应的合并规则解决和避免合并冲突。对于不同的 Manifest 文件中同一个属性的不同值,在合并的时候还需要优先级来进行判断,用高优先级的去覆盖低优先级的。
关于优先级定义如下:
合并规则:概括来说是这样:
示例:现在给出一些例子说明上述规则,我的主 module 名为 app ,新建一个依赖的 module 叫 uisdk ,现在分别给出两个 module 的 build.gradle 文件:
app/build.gradle
apply plugin: 'com.android.application' android { compileSdkVersion 24 buildToolsVersion "24.0.0" defaultConfig { applicationId "com.example.rth.study" minSdkVersion 15 targetSdkVersion 24 versionCode 1 versionName "1.0" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } productFlavors { demo { minSdkVersion 7 applicationId "com.rth.app" } } } dependencies { compile fileTree(include: ['*.jar'], dir: 'libs') testCompile 'junit:junit:4.12' compile 'com.android.support:appcompat-v7:24.0.0' compile project(':uisdk') }
uisdk/build.gradle
apply plugin: 'com.android.library' android { compileSdkVersion 24 buildToolsVersion "24.0.0" defaultConfig { minSdkVersion 8 targetSdkVersion 24 versionCode 1 versionName "1.0" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) testCompile 'junit:junit:4.12' compile 'com.android.support:appcompat-v7:24.0.0' }
在 app/build.gradle 里面,defaultConfig 的 minSdkVersion 为15,但我在变种版本(productFlavors 里的 demo)里设置的 minSdkVersion 为7,最终 app 的 Manifest 的 minSdkVersion 就为7,再看 uisdk 里面的 build.gradle ,minSdkVersion 为8,就是说 app 这个 module 和 uisdk 这个 module library 在同一个属性上使用了不同的非默认值,而且 library 的 Manifest 属于最低优先级,它设置的值又比优先级比它高的值还要高,就会出错,出错信息的描述也很清晰:
Error:Execution failed for task ':app:processDemoDebugManifest'. Manifest merger failed : uses-sdk:minSdkVersion 7 cannot be smaller than version 8 declared in library ... Suggestion: use tools:overrideLibrary="com.example.uisdk" to force usage
根据错误信息,我们有两种方式解决这个问题:
<uses-sdk tools:overrideLibrary="com.example.uisdk"/>
就能编译通过了,这适用于比较特殊的情况,就是在依赖库里可能要适用一些新特性,这些特性在 app 的 minSdkVersion 下不能使用,而且 app 的 minSdkVersion 已经不能更改了。
标记选择器(Marker Selectors) :选择器的功能可以让一些属性在某些 libary 里面无效,比如就拿上面的例子来说,我想让 uisdk 只处理 ui 上的东西,不想让他具有网络访问的功能,那么我可以这么设置:
<uses-permission android:name="android.permission.INTERNET" tools:node="remove" tools:html" target="_blank">selector="com.example.uisdk" />
其中 tools:node 标签表示删除该权限,tools:selector 标签选择在哪个依赖库里执行 tools:node 表示的动作。
可以看出这些配置还是挺灵活的。
Configure dependencies - 配置依赖
这个应该是最熟悉的了,项目中经常要依赖第三方库,一个典型了例子如下:
android {...} ... dependencies { //将本地 module library 编译到项目中 compile project(":mylibrary") //编译远程依赖 compile 'com.android.support:appcompat-v7:23.4.0' //编译本地 jar 包 compile fileTree(dir: 'libs', include: ['*.jar']) }
上面主要用到的方式是 compile ,gradle 支持6种编译方式:
另外在进行 sdk 开发时,一般为了减小 sdk 体积,一些依赖库会用 provided 的方式,同时需要注意的是,对于远程依赖,compile 和 provided 的效果一样,都不会打包到 jar 包或者 arr 包中,但对于本地的 jar 包或者 arr 包的依赖,compile 和 provided 就有区别了。
Configure Sigining - 配置签名
在用 gradle 配置 release 版本的签名信息时,需要下面三个步骤:
示例如下:
android { ... defaultConfig {...} signingConfigs { release { storeFile file("myreleasekey.keystore") storePassword "password" keyAlias "MyReleaseKey" keyPassword "password" } } buildTypes { release { ... signingConfig signingConfigs.release } } }
上面的配置中直接显示了一些敏感信息,比如各种密码,一种更加安全的方式是通过环境变量的方式获取:
storePassword System.getenv("KSTOREWD"); keyPassword System.getenv("KEYPWD");
或者如果使用命令行的方式编译,还可以让用户在命令行输入密码:
storePassword System.console().readLine("\nKeystore password: ") keyPassword System.console().readLine("\nKey password: ")
暂时就总结到这么多了,再次说明,如果发现理解错的地方欢迎指正!!!
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对小牛知识库的支持。
本文向大家介绍你知道 标签的target属性规定在何处打开链接文档吗?相关面试题,主要包含被问及你知道 标签的target属性规定在何处打开链接文档吗?时的应答技巧和注意事项,需要的朋友参考一下 _self 自身打开,效果即跳转 _blank 新开标签页打开 _parent 父 _top 顶级 我们常用的恐怕一般只有2种,_blank,_self 另外有个细节是为什么链接是a标签,而不是b,c呢,
前言 作为一名程序员, 不可能不与网络打交道. 现在我们的手机, 电脑, 不夸张地说, 离开了网络就是一块’废铁’, 它们的作用将大打折扣.. 本文的作用呢, 主要是针对不是非网络专业开发的人员准备的, 以’最短的时间, 了解计网最多的知识’为前提起笔. 目录 概述 物理层 数据链路层 网络层 传输层 应用层 概述 先来了解下各种我们知道, 但是不太了解的专业名词的意思 因特网 因特网是当今世界上
本文向大家介绍canvas知识总结,包括了canvas知识总结的使用技巧和注意事项,需要的朋友参考一下 1.基础知识 canvas元素绘制图像的时候有两种方法,分别是 style:在进行图形绘制前,要设置好绘图的样式 context.arc(centerx圆心横左边,centery圆心纵坐标,radius半径,startingAngle起始弧度值,endingAngle结束弧度值,anticloc
在类的继承中,如果重定义某个方法,该方法会覆盖父类的同名方法,但有时,我们希望能同时实现父类的功能,这时,我们就需要调用父类的方法了,可通过使用 super 来实现,比如: class Animal(object): def __init__(self, name): self.name = name def greet(self): print '
本文向大家介绍C++基础知识总结,包括了C++基础知识总结的使用技巧和注意事项,需要的朋友参考一下 不管是自我定位太高,还是职位层次太低,系统复习了一遍很久没有摸过的C++总是有好处的。总结如下: 一、new和malloc的区别 1、new和delete配对,释放数组需要用delete[]。new和delete实际上调用了malloc和free,另外调用了类的构造函数和析构函数。 2、malloc
本文向大家介绍21个你应该知道的Ruby编程技巧,包括了21个你应该知道的Ruby编程技巧的使用技巧和注意事项,需要的朋友参考一下 1. 快速获取正则表达式的匹配值 通常我们使用正则表达式,都是先match,然后再取结果,但是这样有时候会抛异常,看下面例子: 上面例子中还有一种更简单的方法,就是使用 String#[]方法,可以直接匹配正则表达式,更简洁,虽然看起来使用了魔鬼数字。 当然你可以省略