前言
这篇文章主要描述四个部分:
- 如何生成一个证书
- gradle如何配置
- 批量打包
- 批量拷贝文件
如何生成一个证书
生成一个证书还是很简单了,需要完成下面的三步走:
第一步,点击build->选择Generate Signed APK,如下图:
第二步,选择Generate Signed APK之后点击下一步,进入下图页面,并点击create new key store(图中圈出部分)
第三步,在 Android Studio 中创建新的密钥库:
密钥库
- Key store path:选择创建密钥库的位置。
- Password:为您的密钥库创建并确认一个安全的密码。
密钥
- Alias:为您的密钥输入一个标识名。
- Password:为您的密钥创建并确认一个安全的密码。此密码应当与您为密钥库选择的密码不同
- Validity (years):以年为单位设置密钥的有效时长。密钥的有效期应至少为 25 年,以便您可以在应用的整个生命期内使用相同的密钥签署应用更新。
- Certificate:为证书输入一些关于您自己的信息。此信息不会显示在应用中,但会作为 APK 的一部分包含在您的证书中。
表单如下图,填写完成后点击 OK。
这种生成证书的方式不仅是这一种,但是这种事我认为的最简单最傻瓜式的,其他的生成证书方式如命令行的形式以及其他形式,有兴趣的可以参考下列文档
参考文档
gradle配置
如果使用上述方式,每次打包的时候都要点好几次,但是项目一旦运行在没有配置证书的电脑上,还要复制已经生成好的证书,重新输入密码进行配置,感觉有点小繁琐,那么现在只要在gradle进行一番配置就可以免除这些烦恼。看下面是如何配置的。
下文出现的aidl.jks文件是我用第一种方法生成好的证书,放在App文件下,文后提供了源码可供参考
android {
compileSdkVersion 27
defaultConfig {
//唯一标识一个app,修改这个可以在多渠道打包时,让同个app的不同构建包同时安装在一台设备上
applicationId "com.test.aidl"
//指定运行需要的最小API版本
minSdkVersion 19
//指定用来测试的API版本
targetSdkVersion 27
//app版本号
versionCode 1
//app版本名
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
//签名
signingConfigs {
release {
storeFile file("aidl.jks")
storePassword "123456"
keyAlias "key"
keyPassword "123456"
}
debug {
storeFile file("aidl.jks")
storePassword "123456"
keyAlias "key"
keyPassword "123456"
}
}
buildTypes {
release {
minifyEnabled false //不启用Proguard
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.release
}
debug {
minifyEnabled false //不启用Proguard
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.debug
}
}
}
如此gradle就配置好了
批量打包
如果公司有需求要统计各大平台的App下载量,那么就会牵扯到将包名更改成指定的内容,如果只是改一两个那么我们手动改一下也无所谓,可是要是有10个20 个呢,那。。。手动更改包名就要累死宝宝们了,所以gradle 又帮我们一个大忙,可以编写代码进行批量打包,代码如下:
这里呢为了避免app包下的build.gradle文件过于冗长,我将批量打包的代码提出来了,放在cpoyApk.gradle文件中,cpoyApk.gradle文件存在的位置如下图
在build.gradle文件中头部添加下面这句话,将文件引入
apply from: this.file('copyApk.gradle')
在cpoyApk.gradle文件中代码:
this.android.flavorDimensions 'type'
this.android.productFlavors {
//定义各大平台的名字
googlepay {
dimension 'type'
manifestPlaceholders = [MTA_CHANNEL_VALUE: "googlepay"]
}
baidu {
dimension 'type'
manifestPlaceholders = [MTA_CHANNEL_VALUE: "baidu"]
}
qihoo360 {
dimension 'type'
manifestPlaceholders = [MTA_CHANNEL_VALUE: "qihoo360"]
}
xiaomi {
dimension 'type'
manifestPlaceholders = [MTA_CHANNEL_VALUE: "xiaomi"]
}
tencent {
dimension 'type'
manifestPlaceholders = [MTA_CHANNEL_VALUE: "tencent"]
}
anzhi {
dimension 'type'
manifestPlaceholders = [MTA_CHANNEL_VALUE: "anzhi"]
}
}
// 指定apk名字输出格式
this.android.applicationVariants.all { variant ->
variant.outputs.all {
outputFileName = "aidl_${this.android.defaultConfig.versionName}_" +
"${this.android.defaultConfig.versionCode}_" +
"${variant.productFlavors[0].name}.apk"
}
}
打包之后,所生成的apk的包名如下
我们可以看一下运行完上面的gradle代码,项目中的task有没有什么变化
mac系统可以使用终端找到当前项目,输入./gradlew task命令
Windows系统也可以在终端找到当前项目,输入gradlew task命令
会出现下面的task目录,这里只是截取了一部分,每个task后面都有对应的解释(黄色的就是解释)
如果不想输入命令行查看呢,也可在Android Studio最右边点击Gradle->app->Tasks->build
查看,如下图所示,同样可以查看task
那我为什么要介绍怎么查看task呢,那是因为。。。如果你只想生成360平台的apk,那么你找到assembleQihoo360 双击,就可以生成调试的apk以及正式的Apk,是不是很简单,或者是使用命令行./gradlew assembleQihoo360(mac系统下,Windows系统下将./去掉即可)
我们可以看下运行效果:
批量拷贝文件
批量打包文件已经完成了,那我们总不能一个一个的把文件拷出来放在指定的目录下吧,于是乎,我又想到了用gradle实现批量拷贝文件到指定目录下,还是在cpoyApk.gradle文件中,代码如下:
//自定义copyApk task
task copyTask {
doLast {
def apkNameList = [
"anzhi",
"baidu",
"googlepay",
"qihoo360",
"tencent",
"xiaomi"
]
//遍历
apkNameList.each { def content ->
def fileName = "aidl_${this.android.defaultConfig.versionName}_" +
"${this.android.defaultConfig.versionCode}_" +
"${content}.apk"
// 拷贝文件的始发地
def sourceFile = "./build/outputs/apk/${content}/debug/" + fileName
// 指定文件拷贝的目的地
def destationFile = new File(project.getProjectDir().path + "apk/")
try {
// 判断文件夹是否存在
if (!destationFile.exists()) {
destationFile.mkdir()
}
//拷贝
copy {
from sourceFile
into destationFile
rename {
fileName
}
}
} catch (Exception e) {
e.printStackTrace()
}
}
}
}
这代码里是自定义了一个task,执行./gradlew copyTask,可以看到根目录下出现appapk文件夹,并且里面包含各大平台正式的apk,效果如下:
但是光自定义task是不行的,还需要将自定义的task挂接到构建过程中,代码如下:
//挂接自定义task到构建过程中
this.project.afterEvaluate { project ->
// 获得build task
def buildTask = project.tasks.getByName('build')
if (buildTask == null) {
throw GradleException('the build task is not found')
}
buildTask.doLast {
copyTask.execute()
}
}
最后我们来看下执行效果:
github地址