Android gradle自动化加固签名下载apk

779 阅读3分钟

gradle+360加固宝实现自动化打包、加固、签名输出

由于我司应用已经上架到各大应用市场,每次发布版本都要:先打包,然后打开360加固宝,上传安装包,等待加固,加固完再手动下载然后上传应用市场,整个过程特别麻烦。为了偷懒就想着有没有更方便的方法,打包完成自动加固签名,于是网上搜索了一堆gradle自动化打包加固的插件,想象很美好引入别人封装的加固插件,发现打包完成并不能成功调用360加固。折腾了2天,发现这些插件其多是针对windows环境的,而我使用的是mac环境开发。所以便有了这篇文章,借此记录下自己遇到的问题,也希望能帮到使用mac开发的安卓童鞋。

好了下面直接上代码:(其实也不算代码,主要就是一个.gradle脚本文件)

首先:

出于安全考虑,keystore/jks 文件路径、密码等建议放在local.properties文件中,如下:

#你们自己的签名文件路径
STORE_FILE=/Users/laowang/keysore/demo.jks
#签名文件秘码
STORE_PASSWORD=demo123456
#签名文件别名
KEY_ALIAS=demo
KEY_PASSWORD=demo123456

#你自己的360用户名
JiaGuUserName=testjiagu
#你自己的360密码
JiaGuPassword=123456789

新建加固gradle脚本:

在app目录下,(注意:是app目录下,不是项目根目录下)新建一个名为pack.gradle的文件,至于前缀名字叫啥你随意【doge】,内容如下:

/**
 * description:360自动加固
 */

// 把敏感信息存放到自定义的properties文件中
def propertiesFile = rootProject.file("local.properties")
def properties = new Properties()
properties.load(new FileInputStream(propertiesFile))

ext {
    // 签名配置
    signing = [keyAlias     : properties['KEY_ALIAS'],
               keyPassword  : properties['STORE_PASSWORD'],
               storeFile    : properties['STORE_FILE'],
               storePassword: properties['STORE_PASSWORD']
    ]

    // app相关的配置
    app = [
            //默认release apk的文件路径,因为加固是基于release包的
            releasePath: "${project.buildDir}/outputs/apk/release",
            //对release apk 加固后产生的加固apk地址
            packersPath: "${project.buildDir}/outputs/packers",

    ]

    // 360加固配置
    packers = [account          : properties['JiaGuUserName'], //账号
               password         : properties['JiaGuPassword'],  //密码
               zipPath          : "${project.rootDir}/jiagu/360jiagu.zip",  //加固压缩包路径
               unzipPath        : "${project.rootDir}/jiagu/360jiagu/",  //加固解压路径
               jiaguPath        : "${project.rootDir}/jiagu/360jiagu/360jiagubao/jiagu/",
               jarPath          : "${project.rootDir}/jiagu/360jiagu/360jiagubao/jiagu/jiagu.jar",  //执行命令的jar包路径
               channelConfigPath: "${project.rootDir}/jiagu/Channel.txt",  //加固多渠道
               jiagubao_mac     : "https://down.360safe.com/360Jiagu/360jiagubao_mac.zip",  //加固mac下载地址
               jiagubao_windows : "https://down.360safe.com/360Jiagu/360jiagubao_windows_64.zip", //加固widnows下载地址
               windowsCmdStart  : 'java',    //windows环境下java命令开头
               macCmdStart      : 'java/bin/java',//mac环境下java命令开头
    ]
}

/**
 *  360加固,适用于新后台打包
 */
task packersNewRelease {
    group 'packers'
    dependsOn 'assembleRelease'
    doLast {
        //删除加固后的渠道包
        deleteFile()
        // 下载360加固文件
        download360jiagu()
        // 寻找打包文件release apk
        def releaseFile = findReleaseApk()
        if (releaseFile != null) {
            //执行加固签名
            packers360(releaseFile)

        } else {
            println 'packers===can't find release apk and can't excute 360 jiagu'
        }
    }
}



/**
 *  加固后,打新版本的渠道包时,同时生成老版本的渠道包
 */
task packersRelease {
    group 'packers'
    dependsOn packersNewRelease

    doLast {
        println "packers===packersRelease finished"
    }
}

/**
 *  对于release apk 进行360加固
 */
def packers360(File releaseApk) {
    println 'packers===beginning 360 jiagu'
    def packersFile = file(app["packersPath"])
    if (!packersFile.exists()) {
        packersFile.mkdir()
    }


    exec {
        workingDir(packers["jiaguPath"])
        // 登录360加固保
        executable = isWindows() ? packers["windowsCmdStart"] : packers["macCmdStart"]
        args = ['-jar', packers["jarPath"], '-login', packers["account"], packers["password"]]
        println 'packers===import 360 login'
    }
    exec {
        workingDir(packers["jiaguPath"])
        // 导入签名信息
        executable = isWindows() ? packers["windowsCmdStart"] : packers["macCmdStart"]
        args = ['-jar', packers["jarPath"], '-importsign', signing["storeFile"],
                signing["storePassword"], signing["keyAlias"], signing["keyPassword"]]
        println 'packers===import 360 sign'
    }
    exec {
        workingDir(packers["jiaguPath"])
        // 查看360加固签名信息
        executable = isWindows() ? packers["windowsCmdStart"] : packers["macCmdStart"]
        args = ['-jar', packers["jarPath"], '-showsign']
        println 'packers===show 360 sign'
    }
    exec {
        workingDir(packers["jiaguPath"])
        // 初始化加固服务配置,后面可不带参数
        executable = isWindows() ? packers["windowsCmdStart"] : packers["macCmdStart"]
        args = ['-jar', packers["jarPath"], '-config']
        println 'packers===init 360 services'
    }
    exec {
        workingDir(packers["jiaguPath"])
        // 执行加固
        executable = isWindows() ? packers["windowsCmdStart"] : packers["macCmdStart"]
        args = ['-jar', packers["jarPath"], '-jiagu', releaseApk.absolutePath, app["packersPath"], '-autosign']
        println 'packers===excute 360 jiagu'
    }
    println 'packers===360 jiagu finished'
    println "packers===360 jiagu path ${app["packersPath"]}"
}

/**
 * 自动下载360加固保,也可以自己下载然后放到根目录
 */
def download360jiagu() {
    // 下载360压缩包
    File zipFile = file(packers["zipPath"])
    if (!zipFile.exists()) {
        if (!zipFile.parentFile.exists()) {
            zipFile.parentFile.mkdirs()
            println("packers===create parentFile jiagu ${zipFile.parentFile.absolutePath}")
        }
        // 加固保的下载地址
        def downloadUrl = isWindows() ? packers["jiagubao_windows"] : packers["jiagubao_mac"]
        // mac自带curl命令 windows需要下载curl安装
        def cmd = "curl -o ${packers["zipPath"]} ${downloadUrl}"
        println cmd
        cmd.execute().waitForProcessOutput(System.out, System.err)
    }
    File unzipFile = file(packers["unzipPath"])
    if (!unzipFile.exists()) {
        //解压 Zip 文件
        ant.unzip(src: packers["zipPath"], dest: packers["unzipPath"], encoding: "GBK")
        //println "unZipFile child == ${unzipFile.listFiles()[0].name}"
        //重命名加固文件夹
        File jiaguFile = unzipFile.listFiles()[0]
        String filePath="${jiaguFile.parentFile.path}/360jiagubao"
        File newFile= file(filePath)
        jiaguFile.renameTo(newFile)
        println 'packers===unzip 360jiagu'
        //将解压后的文件开启读写权限,防止执行 Jar 文件没有权限执行,windows需要自己手动改
        if (!isWindows()) {
            def cmd = "chmod -R 777 ${packers["unzipPath"]}"
            println cmd
            cmd.execute().waitForProcessOutput(System.out, System.err)
        }
    }
}



/**
 *  是否是windows系统
 * @return
 */
static Boolean isWindows() {
    return System.properties['os.name'].contains('Windows')
}

/**
 * 寻找本地的release  apk
 * @return true
 */
def deleteFile() {
    delete app["packersPath"]
    println 'packers===delete all file'
}

/**
 * 首先打一个release包,然后找到当前的文件进行加固
 * @return releaseApk
 */
def findReleaseApk() {
    def apkDir = file(app["releasePath"])
    File releaseApk = apkDir.listFiles().find { it.isFile() && it.name.endsWith(".apk") }
    println "packers===find release apk ${releaseApk.name}"
    return releaseApk
}
/**
 *  加固输出并且重新命名
 * @return packersApk
 */
def outputpackersApk() {
    File oldApkDir = file(app["packersPath"])
    File oldApk = oldApkDir.listFiles().find { it.isFile() && it.name.contains("jiagu") }
    println "packers===output pacckers sourceApk ${oldApk.name}"
    copy {
        from app["packersPath"] + File.separator + oldApk.name
        into app["packersPath"]
        rename(oldApk.name, "release.apk")
        println 'packers===output pacckers renameApk release.apk'
    }
    File newApk = oldApkDir.listFiles().find { it.isFile() && it.name.equals("release.apk") }
    println "packers===output packers renameApk${newApk.absolutePath}"
    return newApk.absolutePath
}

使用:

在app目录下的build.gradle 中引用我们上面新建的pack.gradle文件:

plugins {
    id 'com.android.application'
    id 'kotlin-android'
    id 'kotlin-android-extensions'
}
//放在plugin闭包下面
//360加固签名配置脚本
apply from :"pack.gradle"

在项目terminal窗口输入:./gradlew packersNewRelease
等待打包加固完即可。如果不想输入命令也可以这样:

截屏2021-12-10 下午3.50.54.png

看到下面的输出结果,说明你成功了(oh yeah):

截屏2021-12-10 下午3.59.47.png

最后,本人也算开发小白,大家一起共勉,以上内容有误的地方请轻拍。。。

感谢# 折扇画卿颜