Android如何在gradle中配置V3签名轮替

196 阅读1分钟

概述

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