概述
Android的v3签名增加了签名替换的能力,主要是为了解决签名过期的问题,目前绝大部分App应该还不会遇到,但偏偏就有App遇到了😮💨。使用新的apksigner确实能解决,但是AGP插件却没有支持密钥替换(signingConfigs.enableV3Signing
只是增强安全性),为了方便打包,我们可以自定义一个gradle插件来对apk进行重签名。
方案流程
通过applicationVariants
找到apk打包的最后一个Task:PackageAndroidArtifact
,在Task结束的时候增加重签名逻辑,这样就可以不用修改原有的打包命令。
project.logger.info("do v3 signing")
val appExtension = project.extensions.findByName("android") as AppExtension
val v3SigningConfig = project.extensions.findByName("V3SigningConfig") as V3SigningConfig
val separator = File.separator
val packageTask = variant.packageApplicationProvider.get()
val apkFiles = packageTask.outputs.files.asFileTree.files.filter { file -> file.isFile && file.extension == "apk" }
val buildToolDir = "${appExtension.sdkDirectory.absolutePath}${separator}build-tools${separator}${appExtension.buildToolsVersion}${separator}"
val apkSignerExe = if (isWindows()) "${buildToolDir}apksigner.bat" else "${buildToolDir}apksigner"
apkFiles.forEach { apkFile ->
val v3File = "${apkFile.parentFile.absolutePath}${separator}${apkFile.name}.v3"
val ret = project.exec { execSpec ->
execSpec.executable = apkSignerExe
execSpec.args("sign")
execSpec.args("--ks")
execSpec.args(v3SigningConfig.oldKeyStore?.storeFile?.absolutePath)
execSpec.args("--ks-pass")
execSpec.args("pass:${v3SigningConfig.oldKeyStore?.storePassword}")
execSpec.args("--next-signer")
execSpec.args("--ks")
execSpec.args(v3SigningConfig.newKeyStore?.storeFile?.absolutePath)
execSpec.args("--ks-pass")
execSpec.args("pass:${v3SigningConfig.newKeyStore?.storePassword}")
execSpec.args("--lineage")
execSpec.args(v3SigningConfig.lineage?.absolutePath)
execSpec.args("--out")
execSpec.args(v3File)
execSpec.args(apkFile.absolutePath)
}
if (ret.exitValue == 0) {
apkFile.delete()
File(v3File).renameTo(apkFile)
project.logger.info("v3 sign success")
} else {
project.logger.error("v3 signer failed: ${ret.exitValue}")
}
}
配置方式
build.gradle.kts
plugins {
// 放在最下面
id("com.blookliu.v3-rotate-signer")
}
V3SigningConfig {
oldKeyStore.storeFile = file("$projectDir/keystores/old-key.keystore")
oldKeyStore.storePassword = "abcd1234"
newKeyStore.storeFile = file("$projectDir/keystores/new-key.keystore")
newKeyStore.storePassword = "abcd1234"
lineage = file("$projectDir/keystores/lineage")
// 是否使用独立的gradle task,v3RotateSign${variantName}
useSingleTask = false
}
具体代码可以参考V3RotateSignerPlugin。