安卓通过Gradle Task实现多平台自动下载360加固资源、瓦力打渠道包的自动打包流程

自定义gradle Task实现打包+360加固+瓦力打渠道包流程

  • 在这里我们实现了通过gradle task窗口一键执行打包—>下载360加固包—>解压—>加固—>瓦力打渠道包—>生成最终zip包流程,兼容win/mac/linux多平台。
  • 众所周知,gradle编译过程是通过内部的各种task和transform进行实现的,这也是现在gradle的两大概念,两者关系:addTransform 方法在执行过程中,会将 Transform 包装成一个 AndroidTask 对象,所以transfrom最终会被转换成一个task。例如常用的clean,assemble等任务。
    先来一张最终gradle效果图:
    最终gradle效果图

一、为项目配置签名文件和buildTypes

  1. 生成项目的打包签名文件,相信大家都会,没什么好讲解的,下面一图带过创建签名文件

  2. 创建签名文件之后,一般都放置在项目根目录下(没有强制要求),然后就是把签名文件配置起来了,如果位置不是根目录记得修改相对应的路径。

  3. 首先呢,我们先在根目录下创建一个config.gradle文件用来储存我们的签名信息等文件。(特别说明。此处建议用properties文件来存储敏感信息,避免信息泄露。)

    # 调试签名信息
    KEY_MOBILE_ALIAS=keyalias
    KEY_FILE=../autopack_key.jks
    # 此处签名密码  和别名密码是一样的 故一个字段代表
    KEY_PASSWORD=123456
    #版本号
    VERSION_CODE=1
    VERSION_NAME=1.1
    
  4. .在项目根目录下的build.gradle引用config.gradle

    apply from: 'config.gradle'
    
  5. 随后就可以在app下的build.gradle文件中设置签名信息

    android {
    	//其他配置
    	.........
    	signingConfigs {
        	keyConfig {
            	keyAlias KEY_MOBILE_ALIAS
            	keyPassword KEY_PASSWORD
            	storeFile file(KEY_FILE)
            	storePassword KEY_PASSWORD
       	 }
    	}
    }
    
  6. 接着在app下的build.gradle中设置打包方式buildTypes,并设置打包取用方才设置的签名信息。

    android {
    	//其他配置
    	.........
    	buildTypes {
        	debug {
            	minifyEnabled false
            	proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
            	resValue 'string', 'app_name', "AutoPackDebug"
            	signingConfig signingConfigs.keyConfig
        	}
        	beta {
            	minifyEnabled false
            	proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
            	resValue 'string', 'app_name', "AutoPackBeta"
            	signingConfig signingConfigs.keyConfig
        	}
        	release {
            	minifyEnabled true
            	proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
            	resValue 'string', 'app_name', "AutoPackRelease"
            	signingConfig signingConfigs.keyConfig
        }
    }
    

    这里说明一下resValue属性 ,属性动态设置该模式下打包apk文件的应用名,即不同打包安装后在手机上显示的对应名称。

  7. 签名文件和打包方式都设置了,那么还需要设置一下build目录下打包出的apk文件名称,也方便后边我们自动打包取打包apk的路径和相关命名信息。

    android {
    	//其他配置
    	.........
    	applicationVariants.all { variant ->
        variant.outputs.all { output ->
            def newName
            newName = 'auto_pack_' + VERSION_NAME + '_' + variant.buildType.name + '.apk'
            outputFileName = new File(newName)
        }
    }
    }
    

    VERSION_NAME即为前边在config.gradle中设置的版本名称

到此打包这块的东西就设置完成了。

二、创建gradle task任务执行加固流程

要实现对打出的包进行加固,我们必须要用到三方平台的工具了,此处我们用的是360加固资源,优势就是可以命令行进行所有操作。那么问题来了,因为开发人员可能用的系统既有win,也有mac,说不定还有linux,那么为了不让项目因为加固变得臃肿,在此就想出了根据当前系统下载对应的加固资源,在进行解压加固一系列操作。那么久开始干起来把!!
先来一个打印彩色日志的方法,下方使用的 color_print 代码如下:

	def color_print(String value) {
		//黄色 常规信息打印
    	printf "\033[1;33m❤❤❤%s\033[0m\n", value
	}
	def color_printSuccess(String value) {
		//绿色 成功信息打印
    	printf "\033[1;32m❤❤❤%s\033[0m\n", value
	}
	def color_printError(String value) {
	//绿色 错误信息打印
    printf "\033[1;31m💀💀💀💀\t%s\033[0m\n", value
}

接着我们就来实现各种需要用的得task,如下

1. 自动化相关目录资源声明
  • 项目根目录下创建加固资源和相关apk存放成目录_autoPack,并在_autoPack下创建jiagu.gradle用来创建task。内部相关文件夹请看下图:在这里插入图片描述

    jiagu文件夹是360自动下载资源存放位置(无需手动创建)
    output文件夹是流程中加固、渠道包文件存放位置(无需手动创建)
    walle文件夹是存放美团打渠道包资源存放位置(需要手动创建)

2. 相关task详解

各种task独立创建,使用dependsOn(其含义为依赖某个任务,即在某个任务之后执行,如:a.dependsOn b,要执行task a先执行task b)处理相关任务的依赖关系。

  1. 下载360资源:在其中创建根据当前系统下载360的task,并让其每次执行前都先执行 assembleRelease 打包任务,相关gradle语法如需详细了解请自行百度搜索,并在下载之前进行本地资源文件存在的判断:

     task downloadZipFile(dependsOn: 'assembleRelease') {
     //先判断本地有没有加固文件夹,一般项目第一次clone下来的时候都是不存在的
     //首次需自动下载
     File folder = file(jiaguConfig.jiagu_root_path)
     File file = file(jiaguConfig.jiaguJarPath)
     //enabled属性---是否跳过当前任务
     enabled = !(folder.exists() && file.exists())
     doFirst {
         color_print "执行assembleRelease打包任务完毕"
         if (!enabled) {
             color_print "360加固文件夹 和 加固jar文件存在"
         } else {
             color_print "360加固文件夹或者加固jar文件不存在,为该系统本地下载相关资源包"
         }
     }
     doLast {
         color_print "开始下载加固压缩包 请稍后。。。"
         //TODO 方法一:使用de.undercouch.download 下载资源
     	//        download {
     	//            src getJiaGuZipUrlByOs()
     	//            dest new File(jiaguConfig.download_jiagu_zip_path)
     	//            overwrite false
     	//        }
         //TODO 方法二:使用系统curl命令 下载资源 目前测试window10 mac正常支持
         File zipFile = new File(jiaguConfig.download_jiagu_zip_path)
         if (!zipFile.exists()) {
             if (!zipFile.parentFile.exists()) {
                 zipFile.parentFile.mkdirs()
             }
             def downloadUrl = getJiaGuZipUrlByOs()
             def cmd = "curl -o ${jiaguConfig.download_jiagu_zip_path} ${downloadUrl}"
             cmd.execute().waitForProcessOutput(System.out, System.err)
         }
         color_print "360加固资源包下载完成 路径在" + jiaguConfig.download_jiagu_zip_path
         color_print "准备对该资源包进行解压"
         color_print "执行解压任务 ❤unzipFile❤ 请稍后。。。"
        }
     }
    

    说明 在此用的是curl命令进行下载相关360加固文件的操作,并加了详细的注释

  2. 解压:下载完成后要进行解压,故接着创建解压任务,并依赖上步的下载任务,进行相关文件存在判断,详情见下方代码

     task unzipFile(dependsOn: downloadZipFile, type: Copy) {
     	//onlyIf属性进行条件判断,判断当前任务是否执行
     	onlyIf { downloadZipFile.enabled }
     	from zipTree(jiaguConfig.download_jiagu_zip_path)
    		into jiaguConfig.download_jiagu_path
     	doLast {
         File folder = file(jiaguConfig.download_jiagu_path)
         for (File f : folder.listFiles()) {
             color_print "解压成功:" + f
         }
         color_print "全部解压完成  准备将解压出来的jiagu文件夹复制到" + jiaguConfig.root_path + "文件夹下"
         color_print "执行复制任务 ❤copyDownloadJiaGu❤ 请稍后。。。"
     	}
     }
    
     /**
     * 复制解压下载的加固包中的jiagu文件夹到配置文件夹
      */
     task copyDownloadJiaGu(dependsOn: unzipFile) {
     	onlyIf { downloadZipFile.enabled }
     	//下载的360加固zip解压出的jiagu文件家路径
     	def downnload_jiagu = jiaguConfig.download_jiagu_path + "/jiagu"
     	doFirst {
         	File folder = file(downnload_jiagu)
         	if (!folder.exists()) {
             	File file1 = new File(jiaguConfig.download_jiagu_path)
             	if (file1.exists()) {
                 	color_print "删除资源下载临时目录:" + file1 + "   " + file1.deleteDir()
             	}
             	File file2 = new File(jiaguConfig.jiagu_root_path)
             	if (file2.exists()) {
                 	color_print "删除创建的jiagu文件夹:" + file2 + "   " + file2.deleteDir()
             	}
             	throw new RuntimeException("没有在解压的文件夹中找到jiagu文件夹,请重试 或者 手动官网下载相关360加固文件,将资源包中的jiagu文件夹解压到:" + jiaguConfig.root_path + "文件夹下")
         	}
         	copy {
             	from downnload_jiagu
             	into jiaguConfig.jiagu_root_path
         	}
    	 }
     doLast {
         color_print "复制完成。。。copy " + downnload_jiagu + " to " + jiaguConfig.jiagu_root_path
         File filedir = new File(jiaguConfig.download_jiagu_path)
         color_print "删除下载的资源临时存放文件夹:" + filedir + "   " + filedir.deleteDir()
         color_print "下载加固资源流程结束,开始进行360加固。。。"
    
     }
    }
    
    
  3. 360登录:资源文件准备完毕后就该进行360账号的登录以及登录前的准备工作,请看代码:
    首先要在config.gradle中声明360账号,并在config.properties隐私存储文件给予自己的账号密码,看下放代码应该就懂了:

     //360加固账号密码配置
     	_360 = [
       	     account   : properties['ACCOUNT_360'],
        	 password  : properties['PASSWORD_360']
    	 ]
    

    至于如何读取properties中的信息,可以百度,在此也给出代码:

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

    下方则为登录的 相关任务:

     /**
      * 进行登录
     */
     task login(type: JavaExec, dependsOn: copyDownloadJiaGu) {
    	 workingDir(jiaguConfig.jiagu_root_path)
    	 classpath(files(jiaguConfig.jiaguJarPath))
    	 main('com.qihoo.jiagu.CmdMain')
    	 args('-login', jiaguConfig._360_user_name, jiaguConfig._360_user_pw)
     }
    
     /**
     * 登录前(2) 进行相关文件夹的创建和清空
     */
     login.doFirst {
     	File targetFile = new File(jiaguConfig.targetApkPath)
     	if (!targetFile.exists()) {
      	   throw new RuntimeException("加固apk文件不存在:" + 	targetFile.getAbsolutePath())
         } else {
     	    color_print("开始加固:" + targetFile.getAbsolutePath())
         	color_print("输出渠道包zip路径:" + jiaguConfig.zipOutput)
     	}
     	//创建基础文件夹
     	createFolder(jiaguConfig.walleOutput, true)
     	createFolder(jiaguConfig.zipOutput)
     	createFolder(jiaguConfig.jiaguOutput, true)
     	createFolder(jiaguConfig.tmpOutput, true)
     	checkZipFolderNum(jiaguConfig.zipOutput)
     }
    
     /**
      * 登录前(1)初始化相关路径信息  签名信息
      */
     login.doFirst {
     	project.android.applicationVariants.all { variant ->
     	    //对应app/build.gradle文件声明 buildTypes 下声明的打包类型
     	    if (
     	    (jiaguConfig.likeApkName == "" && variant.name.toLowerCase() == 				"release")
                 || (jiaguConfig.likeApkName != "" && variant.name.toLowerCase().contains(jiaguConfig.likeApkName))
         ) {
             color_print("初始化相关路径信息  签名信息,当前打包方式:" + variant.name.toLowerCase())
             if (jiaguConfig.keystorePath == '') {
                 //自动配置签名信息
                 jiaguConfig.keystorePath = variant.signingConfig.storeFile
                 jiaguConfig.keystorePwd = variant.signingConfig.storePassword
                 jiaguConfig.keystoreAlias = variant.signingConfig.keyAlias
                 jiaguConfig.keystoreAliasPwd = variant.signingConfig.keyPassword
    
    
                 List<String> list = new ArrayList<>()
                 list.add('-importsign')
                 list.add(jiaguConfig.keystorePath)
                 list.add(jiaguConfig.keystorePwd)
                 list.add(jiaguConfig.keystoreAlias)
                 list.add(jiaguConfig.keystoreAliasPwd)
    
                 color_print "使用签名:" + list
    
                 setKeystore.setArgs(list)
             }
    
             variant.outputs.each { output ->
                 //自动配置目标文件路径, 和临时文件名
                 if (jiaguConfig.targetApkPath == "") {
                     jiaguConfig.targetApkPath = output.outputFile.getAbsolutePath()
                     color_print "读取到目标apk路径:" + jiaguConfig.targetApkPath
                 }
    
                 if (jiaguConfig.tmpApkName == '') {
                     jiaguConfig.tmpApkName = output.outputFile.getName()
                     color_print "临时文件名:" + jiaguConfig.tmpApkName
                 }
                 copyTmpApk.rename('(.+)', jiaguConfig.tmpApkName)
    
                 if (jiaguConfig.zipFileName == '') {
                     jiaguConfig.zipFileName = jiaguConfig.tmpApkName
                             .substring(0, jiaguConfig.tmpApkName.lastIndexOf('.')) + "_channel.zip"
                     color_print "zip文件名:" + jiaguConfig.zipFileName
                 }
    
                 zipChannel.archiveName = jiaguConfig.zipFileName
    
                 //重置加固task参数
                 List<String> list = new ArrayList<>()
                 list.add('-jiagu')
                 list.add(jiaguConfig.targetApkPath)
                 list.add(jiaguConfig.jiaguOutput)
                 list.add('-autosign')
                 jiagu360.setArgs(list)
    
                 //重置walle task参数
                 list = new ArrayList<>()
                 list.add('batch')
                 list.add('-f')
                 list.add(jiaguConfig.channelList)
                 list.add(jiaguConfig.tmpOutput + File.separator + jiaguConfig.tmpApkName)
                 list.add(jiaguConfig.walleOutput)
                 walleApk.setArgs(list)
             }
         }
     }
    
  4. 配置本地签名信息:从登录前进行的相关打包数据初始化中取出签名信息配置到本地,代码如下:

    /**
    * 设置签名配置
     */
    task setKeystore(type: JavaExec, dependsOn: login) {
        workingDir(jiaguConfig.jiagu_root_path)
       classpath(files(jiaguConfig.jiaguJarPath))
       main('com.qihoo.jiagu.CmdMain')
    }
    
    /**
    * 显示签名信息
    */
    task showKeystore(type: JavaExec) {
       workingDir(jiaguConfig.jiagu_root_path)
      classpath(files(jiaguConfig.jiaguJarPath))
       main('com.qihoo.jiagu.CmdMain')
     args('-showsign')
    }
    
  5. 加固:取出release包进行加固,代码如下:

    /**
     * 进行加固
    */
    task jiagu360(type: JavaExec, dependsOn: setKeystore) {
    	workingDir(jiaguConfig.jiagu_root_path)
    	classpath(files(jiaguConfig.jiaguJarPath))
    	main('com.qihoo.jiagu.CmdMain')
    }
    
  6. 瓦力渠道包:加固完成后进行渠道包的生成,代码如下:

    /**
    * 瓦力打渠道包
     */
    task walleApk(type: JavaExec, dependsOn: copyTmpApk) {
      workingDir(jiaguConfig.walle_root_path)
     classpath(files(jiaguConfig.walleJarPath))
     main('com.meituan.android.walle.Main')
    }
    

三、对常用task进行分组管理

把我们常用的打包任务进行分组管理,这样的话更方便进行日常使用,并让这些task每次执行的时候先执行clean任务删除上次构建编译的文件,避免出错,详见下方代码,同样添加到jiagu.gradle中:

/**
 * 把声明的 常用打包任务 都转移到_autoPack分组中
 * 并为该任务设置依赖clean关系  即每次自动删除build文件夹
 */
project.afterEvaluate {
    project.android.applicationVariants.all { variant ->
        def pack = 'assemble' + variant.name.capitalize()
        if (null != project.tasks.findByPath(pack) && folder_name != project.tasks.getByName(pack).getGroup()) {
            project.tasks.getByName(pack).setGroup(folder_name)
            project.tasks.getByName(pack).dependsOn('clean')
        }
    }
}

四、结束:附上全部代码

经过上述流程最终完成打包,效果图请看页面最顶部。下面附上整个jiagu。gradle自动打包的全部代码:

import groovy.json.JsonSlurper

apply plugin: 'de.undercouch.download'
/**
 * @Author: stc @Date: 2020/6/14
 * @email: dearstc@163.com
 *
 * ❤-- 使用360加固版本 3.2.2.3 2020-03-16 --❤
 *
 *
 * ❤❤❤----------------------------------------------------------------❤❤❤
 * ❤❤❤--TODO  Task:_autoPack
 * ❤❤❤--  一键打包--下载加固资源文件-360加固-瓦力打渠道包
 * ❤❤❤--  方法一 执行gradle窗口中分组_autoPack下的_autoPack任务即可
 * ❤❤❤--  方法二 Terminal窗口执行(powershell)-->gradle _autoPack
 * ❤❤❤--                            (linux)-->./gradle _autoPack
 * ❤❤❤--        注:前提是配置了gradle的环境变量
 * ❤❤❤--  多平台支持mac/windows/linux
 * ❤❤❤--  声明多个Task是为了方便在执行流程中,更清晰的查阅到执行到那个任务
 * ❤❤❤--  加固文件资源默认是不存在,自动从官网下载,无需特意操作
 * ❤❤❤--  注:❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤
 * ❤❤❤--  注:❤❤❤❤❤❤❤❤❤因为要下载文件到本地  故项目不要放在高权限的目录❤❤❤❤❤❤❤❤❤
 * ❤❤❤--  注:❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤
 * ❤❤❤--  最终渠道包路径请查看打包流程日志,写的很清楚了。
 * ❤❤❤--
 * ❤❤❤--TODO  Task:assembleBetaTo*** / assembleReleaseTo***
 * ❤❤❤--  打包完成上传蒲公英/Fir的Task  依赖于assembleBeta打包
 * ❤❤❤--  assembleBeta打包完成自动上传到蒲公英 输出相关信息  打开短链接
 * ❤❤❤-----------------------------------------------------------------❤❤❤
 * */

/**
 * 360加固文件所在的文件夹名字
 */
def folder_name = "_autoPack"

/**
 * 项目根路径的决定路径
 */
def projectPath = getRootDir().getAbsolutePath()

getRootProject().ext.jiaguConfig = [

        //360 账号 (必须)
        "_360_user_name"         : rootProject.ext._360["account"],
        "_360_user_pw"           : rootProject.ext._360["password"],

        //签名文件配置, 使用空字符, 会自动赋值. (可选)
        "keystorePath"           : '',
        "keystorePwd"            : '',
        "keystoreAlias"          : '',
        "keystoreAliasPwd"       : '',

        //需要加固的APK路径, 如果不存在任务中断执行, 为空:自动根据Gradle配置获取路径 (可选)
        "targetApkPath"          : "",

        //自动查找`targetApkPath`时, 取名字中包含`likeApkName`字符串的路径, 如果有多个, 取第一个
        "likeApkName"            : "",

        //文件所在的根目录
        "root_path"              : projectPath + "/" + folder_name,
        //首次下载360加固的临时存放目录
        "download_jiagu_path"    : projectPath + "/" + folder_name + "/tempdownload",
        //下载360加固包的全路径
        "download_jiagu_zip_path": projectPath + "/" + folder_name + "/tempdownload/360jiagubao.zip",

        //360加固文件所在的根目录
        "jiagu_root_path"        : projectPath + "/" + folder_name + "/jiagu",
        "walle_root_path"        : projectPath + "/" + folder_name + "/walle",

        //渠道文件信息路径
        "channelList"            : projectPath + "/" + folder_name + "/walle/channel",

        //渠道分包后的APK文件名,为空:自动从Gradle脚本中获取 (可选)
        "tmpApkName"             : "",

        //最终生成zip包的文件名 (可选)
        "zipFileName"            : "",

        //360加固jar文件路径
        "jiaguJarPath"           : projectPath + "/" + folder_name + "/jiagu/jiagu.jar",
        //walle分包jar文件路径
        "walleJarPath"           : projectPath + "/" + folder_name + "/walle/walle-cli-all.jar",
        //临时文件输出目录
        "tmpOutput"              : projectPath + "/" + folder_name + "/output/tmp",
        //zip文件输出目录
        "zipOutput"              : projectPath + "/" + folder_name + "/output/zip",
        //加固后文件输出目录
        "jiaguOutput"            : projectPath + "/" + folder_name + "/output/jiagu",
        //walle分包输出目录
        "walleOutput"            : projectPath + "/" + folder_name + "/output/walle",

        //todo 360加固保 首次配置自动下载  下方链接为官方链接,如官方有改动  可改
        //加固mac下载地址
        "jiagubao_mac"           : "https://down.360safe.com/360Jiagu/360jiagubao_mac.zip",
        //加固widnows下载地址
        "jiagubao_windows"       : "https://down.360safe.com/360Jiagu/360jiagubao_windows_64.zip",
        //加固linux下载地址
        "jiagubao_linux"         : "https://down.360safe.com/360Jiagu/360jiagubao_linux_64.zip"

]
//❤❤❤❤❤❤start❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤
/**
 * 把声明的 常用打包任务 都转移到_autoPack分组中
 * 并为该任务设置依赖clean关系  即每次自动删除build文件夹
 */
project.afterEvaluate {
    project.android.applicationVariants.all { variant ->
        def pack = 'assemble' + variant.name.capitalize()
        if (null != project.tasks.findByPath(pack) && folder_name != project.tasks.getByName(pack).getGroup()) {
            project.tasks.getByName(pack).setGroup(folder_name)
            project.tasks.getByName(pack).dependsOn('clean')
        }
    }
}

// 输出执行任务名 用于调试
//gradle.taskGraph.beforeTask { Task task ->
//    println "executing $task ..."
//}
//❤❤❤❤❤❤end❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤


//❤❤❤❤❤❤start打包流程❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤
/**
 * 根据系统下载相应的360加固资源包
 */
task downloadZipFile(dependsOn: 'assembleRelease') {
    //先判断本地有没有加固文件夹,一般项目第一次clone下来的时候都是不存在的
    //首次需自动下载
    File folder = file(jiaguConfig.jiagu_root_path)
    File file = file(jiaguConfig.jiaguJarPath)
    //enabled属性---是否跳过当前任务
    enabled = !(folder.exists() && file.exists())
    doFirst {
        color_print "执行assembleRelease打包任务完毕"
        if (!enabled) {
            color_print "360加固文件夹 和 加固jar文件存在"
        } else {
            color_print "360加固文件夹或者加固jar文件不存在,为该系统本地下载相关资源包"
        }
    }
    doLast {
        //TODO 方法一:使用de.undercouch.download 下载资源
//        download {
//            src getJiaGuZipUrlByOs()
//            dest new File(jiaguConfig.download_jiagu_zip_path)
//            overwrite false
//        }
        //TODO 方法二:使用系统curl命令 下载资源 目前测试window10 mac正常支持
        File zipFile = new File(jiaguConfig.download_jiagu_zip_path)
        if (!zipFile.exists()) {
            if (!zipFile.parentFile.exists()) {
                zipFile.parentFile.mkdirs()
            }
            def downloadUrl = getJiaGuZipUrlByOs()
            def cmd = "curl -o ${jiaguConfig.download_jiagu_zip_path} ${downloadUrl}"
            cmd.execute().waitForProcessOutput(System.out, System.err)
        }
        color_print "360加固资源包下载完成 路径在" + jiaguConfig.download_jiagu_zip_path
        color_print "执行解压任务 ❤unzipFile❤ 请稍后。。。"
    }
}

/**
 * 解压下载的加固包
 */
task unzipFile(dependsOn: downloadZipFile, type: Copy) {
    //onlyIf属性进行条件判断,判断当前任务是否执行
    onlyIf { downloadZipFile.enabled }
    from zipTree(jiaguConfig.download_jiagu_zip_path)
    into jiaguConfig.download_jiagu_path
    doLast {
        File folder = file(jiaguConfig.download_jiagu_path)
        for (File f : folder.listFiles()) {
            color_print "解压成功:" + f
        }
        color_print "全部解压完成  准备将解压出来的jiagu文件夹复制到" + jiaguConfig.root_path + "文件夹下"
        color_print "执行复制任务 ❤copyDownloadJiaGu❤ 请稍后。。。"
    }
}

/**
 * 复制解压下载的加固包中的jiagu文件夹到配置文件夹
 */
task copyDownloadJiaGu(dependsOn: unzipFile) {
    onlyIf { downloadZipFile.enabled }
    //下载的360加固zip解压出的jiagu文件家路径
    def downnload_jiagu = jiaguConfig.download_jiagu_path + "/jiagu"
    doFirst {
        File folder = file(downnload_jiagu)
        if (!folder.exists()) {
            File file1 = new File(jiaguConfig.download_jiagu_path)
            if (file1.exists()) {
                color_print "删除资源下载临时目录:" + file1 + "   " + file1.deleteDir()
            }
            File file2 = new File(jiaguConfig.jiagu_root_path)
            if (file2.exists()) {
                color_print "删除创建的jiagu文件夹:" + file2 + "   " + file2.deleteDir()
            }
            throw new RuntimeException("没有在解压的文件夹中找到jiagu文件夹,请重试 或者 手动官网下载相关360加固文件,将资源包中的jiagu文件夹解压到:" + jiaguConfig.root_path + "文件夹下")
        }
        copy {
            from downnload_jiagu
            into jiaguConfig.jiagu_root_path
        }
    }
    doLast {
        color_print "复制完成。。。copy " + downnload_jiagu + " to " + jiaguConfig.jiagu_root_path
        File filedir = new File(jiaguConfig.download_jiagu_path)
        color_print "删除下载的资源临时存放文件夹:" + filedir + "   " + filedir.deleteDir()
        color_print "下载加固资源流程结束,开始进行360加固。。。"

    }
}


/**
 * 进行登录
 */
task login(type: JavaExec, dependsOn: copyDownloadJiaGu) {
    workingDir(jiaguConfig.jiagu_root_path)
    classpath(files(jiaguConfig.jiaguJarPath))
    main('com.qihoo.jiagu.CmdMain')
    args('-login', jiaguConfig._360_user_name, jiaguConfig._360_user_pw)
}

/**
 * 登录前(2) 进行相关文件夹的创建和清空
 */
login.doFirst {
    File targetFile = new File(jiaguConfig.targetApkPath)
    if (!targetFile.exists()) {
        throw new RuntimeException("加固apk文件不存在:" + targetFile.getAbsolutePath())
    } else {
        color_print("开始加固:" + targetFile.getAbsolutePath())
        color_print("输出渠道包zip路径:" + jiaguConfig.zipOutput)
    }
    //创建基础文件夹
    createFolder(jiaguConfig.walleOutput, true)
    createFolder(jiaguConfig.zipOutput)
    createFolder(jiaguConfig.jiaguOutput, true)
    createFolder(jiaguConfig.tmpOutput, true)
    checkZipFolderNum(jiaguConfig.zipOutput)
}

/**
 * 登录前(1)初始化相关路径信息  签名信息
 */
login.doFirst {
    project.android.applicationVariants.all { variant ->
        //对应app/build.gradle文件声明 buildTypes 下声明的打包类型
        if (
        (jiaguConfig.likeApkName == "" && variant.name.toLowerCase() == "release")
                || (jiaguConfig.likeApkName != "" && variant.name.toLowerCase().contains(jiaguConfig.likeApkName))
        ) {
            color_print("初始化相关路径信息  签名信息,当前打包方式:" + variant.name.toLowerCase())
            if (jiaguConfig.keystorePath == '') {
                //自动配置签名信息
                jiaguConfig.keystorePath = variant.signingConfig.storeFile
                jiaguConfig.keystorePwd = variant.signingConfig.storePassword
                jiaguConfig.keystoreAlias = variant.signingConfig.keyAlias
                jiaguConfig.keystoreAliasPwd = variant.signingConfig.keyPassword


                List<String> list = new ArrayList<>()
                list.add('-importsign')
                list.add(jiaguConfig.keystorePath)
                list.add(jiaguConfig.keystorePwd)
                list.add(jiaguConfig.keystoreAlias)
                list.add(jiaguConfig.keystoreAliasPwd)

                color_print "使用签名:" + list

                setKeystore.setArgs(list)
            }

            variant.outputs.each { output ->
                //自动配置目标文件路径, 和临时文件名
                if (jiaguConfig.targetApkPath == "") {
                    jiaguConfig.targetApkPath = output.outputFile.getAbsolutePath()
                    color_print "读取到目标apk路径:" + jiaguConfig.targetApkPath
                }

                if (jiaguConfig.tmpApkName == '') {
                    jiaguConfig.tmpApkName = output.outputFile.getName()
                    color_print "临时文件名:" + jiaguConfig.tmpApkName
                }
                copyTmpApk.rename('(.+)', jiaguConfig.tmpApkName)

                if (jiaguConfig.zipFileName == '') {
                    jiaguConfig.zipFileName = jiaguConfig.tmpApkName
                            .substring(0, jiaguConfig.tmpApkName.lastIndexOf('.')) + "_channel.zip"
                    color_print "zip文件名:" + jiaguConfig.zipFileName
                }

                zipChannel.archiveName = jiaguConfig.zipFileName

                //重置加固task参数
                List<String> list = new ArrayList<>()
                list.add('-jiagu')
                list.add(jiaguConfig.targetApkPath)
                list.add(jiaguConfig.jiaguOutput)
                list.add('-autosign')
                jiagu360.setArgs(list)

                //重置walle task参数
                list = new ArrayList<>()
                list.add('batch')
                list.add('-f')
                list.add(jiaguConfig.channelList)
                list.add(jiaguConfig.tmpOutput + File.separator + jiaguConfig.tmpApkName)
                list.add(jiaguConfig.walleOutput)
                walleApk.setArgs(list)
            }
        }
    }
}

/**
 * 设置签名配置
 */
task setKeystore(type: JavaExec, dependsOn: login) {
    workingDir(jiaguConfig.jiagu_root_path)
    classpath(files(jiaguConfig.jiaguJarPath))
    main('com.qihoo.jiagu.CmdMain')
}

/**
 * 显示签名信息
 */
task showKeystore(type: JavaExec) {
    workingDir(jiaguConfig.jiagu_root_path)
    classpath(files(jiaguConfig.jiaguJarPath))
    main('com.qihoo.jiagu.CmdMain')
    args('-showsign')
}

/**
 * 进行加固
 */
task jiagu360(type: JavaExec, dependsOn: setKeystore) {
    workingDir(jiaguConfig.jiagu_root_path)
    classpath(files(jiaguConfig.jiaguJarPath))
    main('com.qihoo.jiagu.CmdMain')
}


/**
 * 加固后的包保留,拷贝一份在tmp里面
 */
task copyTmpApk(type: Copy, dependsOn: jiagu360) {
    from(jiaguConfig.jiaguOutput)
    include('*.apk')
    into(jiaguConfig.tmpOutput)
}

/**
 * 瓦力打渠道包
 */
task walleApk(type: JavaExec, dependsOn: copyTmpApk) {
    workingDir(jiaguConfig.walle_root_path)
    classpath(files(jiaguConfig.walleJarPath))
    main('com.meituan.android.walle.Main')
}

/**
 * 瓦力将渠道包打压缩包
 */
task zipChannel(type: Zip, dependsOn: walleApk) {
    //workingDir(baseBuildPath)
    from(jiaguConfig.walleOutput)
    //动态设置
    archiveName(jiaguConfig.zipFileName)
    destinationDir file(jiaguConfig.zipOutput)
}

/**
 * 主任务===》 一键打包--下载加固资源文件-360加固-瓦力打渠道包
 */
task _autoPack(dependsOn: zipChannel, description: '一键打包--下载加固资源文件-360加固-瓦力打渠道包') {
    group folder_name
    doLast {
        color_print "加固打包流程结束:"
        color_printSuccess("渠道包路径:" + jiaguConfig.walleOutput)
        color_printSuccess("zip包路径:" + jiaguConfig.zipOutput)
    }
}

/**
 * 创建路径
 */
def createFolder(String path, boolean clear = false) {
    File folder = file(path)
    if (folder.exists()) {
        if (clear) {
            clearFolder(path)
        }
    } else {
        folder.mkdirs()
    }
}

/**
 * 清理文件夹
 */
def clearFolder(String path) {
    File folder = file(path)
    for (File f : folder.listFiles()) {
        if (f.isDirectory()) {
            clearFolder(f.getAbsolutePath())
        } else if (f.isFile()) {
            color_print "删除文件:" + f + " " + f.delete()
        }
    }
}

/**
 * 检测渠道zip文件夹下压缩包数量,避免过多本地存储
 * 目前设置最多存储五次渠道包历史
 * @param path
 */
def checkZipFolderNum(def path) {
    //文件路径
    List<File> list = getFileSort(path)
    for (int i = 0; i < list.size(); i++) {
        if (i >= 5) {
            color_print "删除历史渠道zip包:" + list.get(i).getName() + " " + list.get(i).delete()
        }
    }
}

/**
 * 获取目录下所有文件(按时间排序)
 *
 * @param path
 * @return
 */
def getFileSort(String path) {

    List<File> list = getFiles(path, new ArrayList<File>())

    if (list != null && list.size() > 0) {

        Collections.sort(list, new Comparator<File>() {
            @Override
            int compare(File file, File newFile) {
                if (file.lastModified() < newFile.lastModified()) {
                    return 1
                } else if (file.lastModified() == newFile.lastModified()) {
                    return 0
                } else {
                    return -1
                }
            }
        })
    }

    return list
}
/**
 * 获取目录下所有文件
 * @param realpath
 * @param files
 * @return
 */
def getFiles(String realpath, List<File> files) {
    File realFile = new File(realpath)
    if (realFile.isDirectory()) {
        File[] subfiles = realFile.listFiles()
        for (File file : subfiles) {
            if (file.isDirectory()) {
                getFiles(file.getAbsolutePath(), files)
            } else {
                files.add(file)
            }
        }
    }
    return files
}

/**
 * 获取当前操作系统的360加固资源下载链接
 */
def getJiaGuZipUrlByOs() {
    def url
    String osName = org.gradle.internal.os.OperatingSystem.current().getName();
    String osVersion = org.gradle.internal.os.OperatingSystem.current().getVersion();
    color_print "当前使用系统 $osName $osVersion was detected."

    if (org.gradle.internal.os.OperatingSystem.current().isLinux()) {
        url = jiaguConfig.jiagubao_linux
    } else if (org.gradle.internal.os.OperatingSystem.current().isWindows()) {
        url = jiaguConfig.jiagubao_windows
    } else if (org.gradle.internal.os.OperatingSystem.current().isMacOsX()) {
        url = jiaguConfig.jiagubao_mac
    } else {
        throw new RuntimeException("不支持当前操作系统:" + osName)
    }
    color_print "对应要下载360加固包的链接地址为:" + url
    return url
}

//❤❤❤❤❤❤end打包流程❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤

五、gradle创建task实现日常自动打包上传到蒲公英或者fir

  1. 为了更完美的解决日常打包问题,提升效率,有了这些还不够,当然还需要实现自动打包到内测平台供测试大佬进行评测。
  2. 实现一键打包并上传测试平台,打印应用下载短连接,并自动打开当前系统默认浏览器进入到该应用下载页面。
  3. 会在下一篇讲解该方案,实现一文件集成所有流程,一键自动化。
  4. 并上传一键自动化Demo,

有需要的点个赞哦,谢谢支持

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值