一、ABI(Application Binary Interface)应用程序二进制接口
其实ABI可以不设置,这样编译时,就会将项目里所有依赖资源包里的so库都打到最终的apk里。 但是,ABI支持多的话,apk也会大,所以一般只支持一种即可。 目前Android 版本,ABI一般配置armeabi-v7a.
注意:
新增so库
新增so库的话,需要在每个在用的文件夹内(armeabi、armeabi-v7a、arm64-v8a ==)放置,否则so库找不到。多个目录,目录下的so库文件数需要相同。
armeabi-v7a 和 armeabi
如果设置支持armeabi-v7a 和 armeabi:如若第三方提供的so只有armeabi,那么armeabi-v7a 内也需要拷贝一份,原因是armeabi-v7a 和 armeabi必须so数一致,且armeabi-v7a支持armeabi hardware does not support
ABI设置错误,可能出现硬件不支持的问题,提示:hardware does not support
二、splits 的属性
1、abi
- 类型:AbiSplitOptions
- 描述:对 abi 进行分包处理,具体我们看下面 AbiSplitOptions 讲解。
2、AbiSplitOptions 类型
2.1 enable
- 描述:是否开启 abi 分包,默认不开启
- 使用:
splits {
abi {
enable true
}
}
效果图如下:
2.2 exclude
描述:排除不需要的架构。
使用:
abi {
// 是否开启
enable true
// 排除不必要的架构
exclude 'x86','arm64-v8a'
}
效果图:
2.3 reset
描述:清除默认架构列表。当我们开启abi 分包时,gradle会帮我们初始化一个架构列表,例如 enable 小节中,我们并没有设置任何架构,而gradle会帮我们分出 “arm64-v8a”、“armeabi-v7a”、“x86”、“x86_64”。
初始化列表会因为gradle的版本不同有所改变
使用:
abi {
// 是否开启
enable true
// 重置包含的目录
reset()
}
2.4 include
描述:设置我们需要的架构。注意的是,我们需要先使用reset方法将默认列表清空,然后再设置。
使用:
abi {
// 是否开启
enable true
// 重置包含的目录,因为已经是包含全部
reset()
// 设置包含,调用前需要先用 reset 将默认清除
include 'armeabi-v7a', 'x86'
}
效果图:
2.5 universalApk
描述:是否编译一个包含全部架构的apk。
使用:
abi {
// 是否开启
enable true
// 是否打出包含全部的apk
universalApk true
}
效果图:
三、sourceSets属性——文件路径配置
sourceSets {
main {
manifest.srcFile 'AndroidManifest.xml' // 指定清单文件
res.srcDirs = ['res'] // 指定res资源目录
assets.srcDirs = ['assets'] // asset资源目录
jni.srcDirs 'src/main/jni' // jni代码目录
jniLibs.srcDir 'src/main/jniLibs' // jni库目录
java.srcDirs = ['src'] // 指定java源代码目录
resources.srcDirs = ['src'] // 指定resource目录
aidl.srcDirs = ['src'] // 指定aidl目录
renderscript.srcDirs = ['src'] // 指定source目录
}
debug.setRoot('build-types/debug') // 指定debug模式的路径
release.setRoot('build-types/release') // 指定release模式的路径
}
四、packagingOptions属性——打包配置
打包配置:
1、pickFirsts:当出现重复文件,会使用第一个匹配的文件打包进入apk
2、merges:当出现重复文件,合并重复的文件打入apk
3、excludes:打包的时候排除匹配的文件
packagingOptions {
pickFirsts = ['META-INF/LICENSE']
//这里不要直接=赋值,避免覆盖掉默认值
merge 'META-INF/LICENSE'
//这里不要直接=赋值,避免覆盖掉默认值
exclude 'META-INF/LICENSE'
}
五、compileOptions属性——Java 的版本配置
compileOptions {
// 在这里你可以进行 Java 的版本配置,
// 以便使用对应版本的一些新特性
}
六、flavorDimensions属性—— 多维度理解(版本差异化打包)
flavorDimensions 从单词字面理解知道是 “风味维度”
是需要结合 “产品风味(即productFlavors)” 来一起使用的。
android {
// 省略其他参数
flavorDimensions 'ENV', "DEVICE_TYPE"
}
定义出两个维度:env和 device_type。一个参数一个维度
多维度理解
其实这涉及到了版本差异化打包的内容,如果说3.0以前的版本差异化打包更多的是为了厂商定制的,那么3.0以后的版本差异化打包就是在厂商的基础之上加入了机型,渠道等一些参数,变成了多个维度的产品。
也就是说之前的一个产品只有一个参数进行描述的话,现在就可以为其增加多个参数进行配置,比如A厂商的A渠道的A机型、A厂商的B渠道的C机型等,维度越多,产品的样式越发丰富。
好了,理论说完,接下来就是进行通俗易懂的一些示例了,只有实践才能让自己检验到真理。
新建项目,然后在app/build.gradle文件里配置两个风味维度(“company”,“channel”),如下:
defaultConfig {
applicationId "com.voctex.flavorsapp"
minSdkVersion 18
targetSdkVersion 27
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
flavorDimensions "company","channel"
}
然后进行产品的多维度配置:
productFlavors{
//随便命名,建议根据该维度的具体信息进行命名
companyA{
dimension "company"
}
companyB{
dimension "company"
}
channelA{
dimension "channel"
}
channelB{
dimension "channel"
}
}
配置完之后,sync构建一下项目。
打包构建之后就会出现多个维度的产品,对应如下,如图:
可以理解为总共有两个维度,公司(company)和渠道(channel),这里公司的维度排前面(排序先后有要求,下面会讲到),所以所有的产品就是,A公司的A渠道产品,A公司的B渠道产品,B公司的A渠道产品,B公司的B渠道产品。
可见,增加维度之后,版本差异化的内容就更为丰富了。
上面说了,维度的定义先后是有要求的,不可随便,下面为了验证这个说法进行了一项测试,我们在productFlavors里给每一个特点产品定义一个常量,常量的值就是该特点产品的名字。如下:
productFlavors{
companyA{
dimension "company"
buildConfigField "String","FLAVOR_NAME","\"companyA\""
}
companyB{
dimension "company"
buildConfigField "String","FLAVOR_NAME","\"companyB\""
}
channelA{
dimension "channel"
buildConfigField "String","FLAVOR_NAME","\"channelA\""
}
channelB{
dimension "channel"
buildConfigField "String","FLAVOR_NAME","\"channelB\""
}
}
这里有个要注意的点就是在BuildConfig定义String的常量时,需要把双引号也加进去。
然后进行跟刚才一样的构建,对比几个风味维度的BuildConfig文件里的这个FLAVOR_NAME常量,会发现总是显示第一维度company的值,而第二维度channel的值并不存在,所以当产生多维度的产品时,定义的一些常量总是以第一维度的配置为准。结果如下:
BuildConfig.java 文件生成后会在app/build/generated/source/buildConfig/companyAChannelA/release/com/voctex/flavorsapp/BuildConfig.java
实验证明,当你在各个维度各自定义了同一个常量的值,总是以第一维度的为准,只有第一维度的定义或者说是修改才是有效的。
七、productFlavors属性——不同渠道发布配置
productFlavors 从字面了解是“产品风味”。他需要和一个风味维度对接,否则会报错。
接着我们上面的例子,使用 productFlavors 定义维度上的风味,使用 dimension
关联。
productFlavors {
// 在这里你可以设置你的产品发布的一些东西,
// 比如你现在一共软件需要发布到不同渠道,
// 且不同渠道中的包名不同,那么可以在此进行配置;
// 甚至可以设置不同的 AndroidManifest.xml 文件。
hebbe {
}
googlePlay {
}
solo {
// applicationId 应用的包名,会覆盖 defaultConfig 中的 applicationId
// applicationId 会替换 AndroidManifest.xml 中的 manifest 标签下 package 的 value
applicationId "com.zinc.power"
// 会追加在 applicationId 字符串的后面,形成最终的包名。
applicationIdSuffix '.debug'
// 风味的维度,指定我们当前风味所所属的维度
dimension 'version'
配置差异化的 logo 和 app名字
manifestPlaceholders = [
logo : "@drawable/logo_bear",
appName : "bear",
]
// 配置签名
signingConfig signingConfigs.xiaopenyou
}
}
七、dependencies属性——项目依赖关系配置
// 指定当前项目的所有依赖关系:本地依赖、库依赖、远程依赖
// 本地依赖:可以对本地 Jar 包或目录添加依赖关系
// 库依赖:可以对项目中的库模块添加依赖关系
// 远程依赖:可以对 jcenter 库上的开源项目添加依赖
// 标准的远程依赖格式是 域名:组织名:版本号
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar']) // 本地依赖
// 远程依赖,com.android.support是域名部分,appcompat-v7是组名称,26.1.0是版本号
implementation 'com.android.support:appcompat-v7:26.1.0'
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
implementation project(':hello') // 库依赖
testImplementation 'junit:junit:4.12' // 声明测试用列库
androidTestImplementation 'com.android.support.test:runner:1.0.1'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
}
参考文章:
Android ABI_android_abi_清风徐来辽的博客-CSDN博客
Android ABI_android_abi_清风徐来辽的博客-CSDN博客
Android 基础知识总结(一) build.gradle文件_build.gradle sourcesets_&岁月不待人&的博客-CSDN博客
Android 打包 flavorDimensions和productFlavors_flavordimensions打包_weixin_50386489的博客-CSDN博客
Android Studio3.0 flavorDimensions多维度理解(版本差异化打包)_安卓为什么要多维度打包_锐湃的博客-CSDN博客