文章目录
- 文档 [Android Plugin DSL Referencel](https://google.github.io/android-gradle-dsl/current/index.html)
- 一 从`build.gradle`文件中分离签名信息
- 二 build.gradle 标签 android{}
- 1. [defaultConfig { } && productFlavors { }](https://google.github.io/android-gradle-dsl/current/com.android.build.gradle.internal.dsl.ProductFlavor.html)
- 2. [aaptOptions { }](https://google.github.io/android-gradle-dsl/current/com.android.build.gradle.internal.dsl.AaptOptions.html)
- 3. [adbOptions { }](https://google.github.io/android-gradle-dsl/current/com.android.build.gradle.internal.dsl.AdbOptions.html#com.android.build.gradle.internal.dsl.AdbOptions:installOptions)
- 4. [buildTypes { }](https://google.github.io/android-gradle-dsl/current/com.android.build.gradle.internal.dsl.BuildType.html)
- 5. [compileOptions { }](https://google.github.io/android-gradle-dsl/current/com.android.build.gradle.internal.CompileOptions.html)
- 6. [dataBinding { }](https://google.github.io/android-gradle-dsl/current/com.android.build.gradle.internal.dsl.DataBindingOptions.html)
- 7. [dexOptions { }](https://google.github.io/android-gradle-dsl/current/com.android.build.gradle.internal.dsl.DexOptions.html)
- 8. [jacoco { }](https://google.github.io/android-gradle-dsl/current/com.android.build.gradle.internal.coverage.JacocoOptions.html)
- 9. [lintOptions { }](https://google.github.io/android-gradle-dsl/current/com.android.build.gradle.internal.dsl.LintOptions.html)
- 10. [packagingOptions { }](https://google.github.io/android-gradle-dsl/current/com.android.build.gradle.internal.dsl.PackagingOptions.html)
- 11. [signingConfigs { }](https://google.github.io/android-gradle-dsl/current/com.android.build.gradle.internal.dsl.SigningConfig.html)
- 12. [sourceSets { }](https://google.github.io/android-gradle-dsl/current/com.android.build.gradle.api.AndroidSourceSet.html)
- 13. [splits { }](https://google.github.io/android-gradle-dsl/current/com.android.build.gradle.internal.dsl.Splits.html)
- 14. [testOptions { }](https://google.github.io/android-gradle-dsl/current/com.android.build.gradle.internal.dsl.TestOptions.html)
- 三 APK 打包自动更换路径以及文件名
文档 Android Plugin DSL Referencel
一 从build.gradle
文件中分离签名信息
如果你是开源项目,建议这么做。否则最好不要暴露签名信息。以下仅供参考。
1. 在项目根目录下创建文件 keystore.properties
:
storePassword="myStorePassword"
keyPassword="mykeyPassword"
keyAlias="myKeyAlias"
storeFile="myStoreFileLocation"
2. 在 build.gradle 文件中如下配置
...
// 创建一个 keystorePropertiesFile 变量,在 rootProject 文件夹下初始化
// keystore.properties 文件.
def keystorePropertiesFile = rootProject.file("keystore.properties")
// 初始化一个新的 Properties() 对象.
def keystoreProperties = new Properties()
// 在 keystoreProperties 对象中加载 keystore.properties 文件keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
android {
signingConfigs {
config {
keyAlias keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPassword']
storeFile file(keystoreProperties['storeFile'])
storePassword keystoreProperties['storePassword']
}
}
}
这样就把签名信息分离出来了,方便了替换。
附:命令行签名
1. 使用命令行生成私钥
$ keytool -genkey -v -keystore my-release-key.keystore
-alias alias_name -keyalg RSA -keysize 2048 -validity 10000
这个命令会提示你输入 keystore 和 key 的密码, 以及一些列信息。-validity
指的是有效期天数。最后会生成 my-release-key.keystore 文件。
2. 编译获取一个 unsigned APK
3. 使用 jarsigner 签名 app
$ jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1
-keystore my-release-key.keystore my_application.apk alias_name
这个命令会提示你输入 keystore 和 key 的密码.
4. 验证签名
$ jarsigner -verify -verbose -certs my_application.apk
也可以通过解压 apk,获取 META-INF 文件夹下的 CERT.RSA 信息进行验证:
keytool -printcert -file CERT.RSA
5. 优化
$ zipalign -v 4 your_project_name-unaligned.apk your_project_name.apk
二 build.gradle 标签 android{}
android 标签下的配置与生成的 BaseExtension.class 里的方法相对应,。
public abstract class BaseExtension implements AndroidConfig{}
AndroidConfig 接口里声明 android 标签的配置,源码如下,所有的属性配置及含义点击查看:BaseExtension .
1. defaultConfig { } && productFlavors { }
配置 App 的产品特性, defaultConfig 是默认的产品特性,自定义的 productFlavors 里的所有特性都各自继承 defaultConfig 的特性。
更有趣的是~~
(1).可以给生成的 BuildConfig 类添加新字段:buildConfigField(type, name, value)
。
(2).添加一个新资源(resValue(类型, 名字, value)
):resValue("string", "apiurl", "http://blog.csdn.net/yang786654260")
,build之后就可以通过 R.string.apiurl 获取,其他类型也一样。
(3).给清单文件中添加可变变量(manifestPlaceholders ),例如:
manifestPlaceholders = [googlekey: "xxxxxxxxxxxx", facebook_app_id: "1111111111",
app_name: "APPPP"]
把配置的 key-value 存在了 map 对象(mManifestPlaceholders)中,build之后在清单文件中动态获取值如下:
android:label="${app_name}"
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="${googlekey}" />
<meta-data
android:name="com.facebook.sdk.ApplicationId"
android:value="${facebook_app_id}" />
建议 把 Key 放到 build.gradle里。
(4).multiDexEnabled, https://developer.android.com/studio/build/multidex.html
,超过 64K 方法的解决办法如下:
build.gradle:
android {
defaultConfig {
// Enabling multidex support.
multiDexEnabled true
}
}
dependencies {
compile 'com.android.support:multidex:1.0.0'
}
Application:
public void onCreate(Bundle arguments) {
MultiDex.install(getTargetContext());
super.onCreate(arguments);
...
}
(5)设置 productFlavors 后,运行 app,就可以在Build Variant 选择相应的版本进行编译。
2. aaptOptions { }
Android Asset Packaging Tool, 是用来打包 APK 是工具。aaptOptions { } 是对打包工具的配置。
3. adbOptions { }
timeOutInMs 用于配置 adb 命令的超时。
installOptions 用于对安装命令的配置,例如:installOptions “-d", "-t"
。
4. buildTypes { }
配置编译类型,可以给 applicationId 加后缀(applicationIdSuffix),配置app名字,配置签名,添加版本号后缀(versionNameSuffix),zipalign ,去除无用资源(shrinkResources),配置混淆文件等。
更有趣的是~~(同 上 )
1.可以给生成的 BuildConfig 类添加新字段:buildConfigField(type, name, value)
。
2.添加一个新资源(resValue(类型, 名字, value)
):resValue("string", "apiurl", "http://blog.csdn.net/yang786654260")
,build之后就可以通过 R.string.apiurl 获取,其他类型也一样。
3.给清单文件中添加可变变量(manifestPlaceholders ),例如:
manifestPlaceholders = [googlekey: "xxxxxxxxxxxx", facebook_app_id: "1111111111",
app_name: "APPPP"]
把配置的 key-value 存在了 map 对象(mManifestPlaceholders)中,build之后在清单文件中动态获取值如下:
android:label="${app_name}"
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="${googlekey}" />
<meta-data
android:name="com.facebook.sdk.ApplicationId"
android:value="${facebook_app_id}" />
建议 把 Key 放到 build.gradle里。
5. compileOptions { }
用于指定 Java 源码和编译的 版本,以及源码的编码格式。
6. dataBinding { }
databinding 的配置。databinding 详解。
7. dexOptions { }
在这里可以配置:
- javaMaxHeapSize(例:“2048m”);
- jumboMode(是否开启jumbo 模式);
- dexInProcess(是否运行 dx 编译器时作为一个独立的进程或内部JVM Gradle守护进程。这样可以极大的提高性能,但是还在实验阶段);
- maxProcessCount(dex最大并发进程,默认是4,并发进程的内存需求:
Total Memory = getMaxProcessCount() * getJavaMaxHeapSize()
, 故这两个的配置要适当以避免 trashing); - preDexLibraries(这可以提高增量构建,但clean构建可能会慢一些。)
- threadCount(dx 运行时使用的线程数,默认是4)
8. jacoco { }
Java Code Coverage, http://www.eclemma.org/jacoco/。
9. lintOptions { }
强大的 lint 的配置。
10. packagingOptions { }
有个错误:Error: duplicate files during packaging of APK,就是在这里解决的:
packagingOptions {
exclude 'META-INF/ASL2.0'
exclude 'META-INF/LICENSE'
exclude 'META-INF/license.txt'
exclude 'META-INF/NOTICE'
exclude 'META-INF/notice.txt'
}
11. signingConfigs { }
签名文件的配置。
12. sourceSets { }
配置各种资源源码路径。例如(下面示例解决了 .so 文件不在 jniLibs 文件夹下就无法识别的Error):
sourceSets {
main {
jniLibs.srcDirs = ['libs']
}
}
13. splits { }
http://tools.android.com/tech-docs/new-build-system/user-guide/apk-splits
14. testOptions { }
注:以上部分配置可以使用 Android Studio 的图形界面,但又局限性。
三 APK 打包自动更换路径以及文件名
Gradle 3.3及以上 使用
release {
signingConfig signingConfigs.release
debuggable false
zipAlignEnabled true
shrinkResources true
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
applicationVariants.all { variant ->
if (variant.buildType.name == "release"){
variant.getPackageApplicationProvider().get().outputDirectory = new File("${rootProject.ext.outputDirectory}")
variant.getPackageApplicationProvider().get().outputScope.apkDatas.forEach { apkData ->
if (apkData != null && apkData.outputFileName.endsWith('release.apk')){
def fileName =
"${getApkPrefixName()}_${variant.productFlavors[0].name}_${defaultConfig.versionCode}_v${defaultConfig.versionName}_${releaseTime()}.apk"
apkData.outputFileName = fileName
}
}
}
}
}
static def releaseTime() {
return new Date().format("yyyyMMdd.kkmm", TimeZone.getTimeZone("GMT+8"))
}
static def getApkPrefixName() {
return "YourApkName"
}
apk打包路径配置
static def isMac() {
return System.properties['os.name'].toLowerCase().contains('mac')
}
static def isWindows() {
return System.properties['os.name'].toLowerCase().contains('windows')
}
static def getSystemUserName(){
return System.properties['user.name']
}
static def getApkSavedPath() {
if (isMac()) {
return "/Users/${getSystemUserName()}/Desktop/release"
}
return "C:/Users/${getSystemUserName()}/Desktop/release"
}
ext {
outputDirectory = getApkSavedPath()
}