Our supertube package needs to be sent to operation personnel for use to prevent security risks caused by leakage. We hope to reinforce the supertube package before uploading it to dandelion.

Our applications generally need to be strengthened and multi-channel packages are generated when they are released. People usually download the reinforcement client or upload the APK file to the management background of the reinforcement service for reinforcement, and then download the installation package file after the reinforcement is completed.

To quote me again:

Time is the most precious asset, and we should use our time wisely.

This article is based on using Gradle to implement a set of code to develop multiple applications in Gradle configuration iterative development, leading everyone to achieve 360 hardened automatic Gradle scripts.

Automatic reinforcement

Our goal is full automation and the ability to execute one line of commands on each team member’s computer without additional configuration.

Download 360 reinforcement program automatically

Complete config.gradle configuration:

ext {
    // Signature file configuration
    signing = [keyAlias : 'xxxxx'.keyPassword : 'xxxxx'.storeFile : '.. /sign.keystore'.               storePassword: 'xxxxxx']

    // The dandelion configuration
    pgy = [apiKey : "xxxx".           uploadUrl: "https://www.pgyer.com/apiv2/app/upload"]

    //360 Hardening configuration
    jiagu = [name : 'xxxxx'.password : 'xxxxx'.zipPath : ".. /jiagu/360jiagu.zip".unzipPath : ".. /jiagu/360jiagubao/".jarPath : '.. /jiagu/360jiagubao/jiagu/jiagu.jar'.             channelConfigPath: '.. /jiagu/Channel.txt'.jiagubao_mac : "http://down.360safe.com/360Jiagu/360jiagubao_mac.zip".jiagubao_windows : "http://down.360safe.com/360Jiagu/360jiagubao_windows_64.zip",
    ]

    android = [compileSdkVersion: 28.minSdkVersion : 19.targetSdkVersion : 28]

    // Version number management
    APP1_VERSION_NAME = "2.0.2"
    APP1_TEST_NUM = "0001"
    APP2_VERSION_NAME = "1.0.5."
    APP2_TEST_NUM = "0005"
}

Copy the code

Create a new jiagu.gradle file:

import org.apache.tools.ant.taskdefs.condition.Os

def downloadUrl = Os.isFamily(Os.FAMILY_WINDOWS) ? rootProject.ext.jiagu["jiagubao_windows"] : rootProject.ext.jiagu["jiagubao_mac"]

def zipPath = rootProject.ext.jiagu["zipPath"]
def unzipPath = rootProject.ext.jiagu["unzipPath"]

task download360jiagu() {
    doFirst {
        // Download the Zip file if it does not exist
        File zipFile = file(zipPath)
        if(! zipFile.exists()) {if(! zipFile.parentFile.exists()) { zipFile.parentFile.mkdirs() } exec { executable ='curl'
                args = ['-o', zipPath, downloadUrl]
            }
        }
    }
    doLast {
        // Decompress the Zip file
        ant.unzip(src: zipPath, dest: unzipPath, encoding: "GBK")
        // Enable read/write permission on the decompressed file to prevent the Jar file from being executed without permission
        exec {
            executable = 'chmod'
            args = ['-R'.'777', unzipPath]
        }
    }
}
Copy the code

Download360jiagu to automatically download and unpack 360 reinforcement programs.

Harden according to multi-channel documents

import org.apache.tools.ant.taskdefs.condition.Os

def downloadUrl = Os.isFamily(Os.FAMILY_WINDOWS) ? rootProject.ext.jiagu["jiagubao_windows"] : rootProject.ext.jiagu["jiagubao_mac"]

def zipPath = rootProject.ext.jiagu["zipPath"]
def unzipPath = rootProject.ext.jiagu["unzipPath"]


// Save path of all APKs after hardening
def APP1_OUTPUT_PATH = "jiagu/apk/app1/"

def APP1_APK_PATH = "${projectDir.absolutePath}/build/outputs/apk/app1Online/release/${getApkName(rootProject.ext.APP1_VERSION_NAME)}"

/** **@paramConfig Configures the hardening option *@paramApkPath File path *@paramOutputPath outputPath *@paramAutomulpkg Whether to automatically generate multi-channel packages */
def jiaGu(String config, String apkPath, String outputPath, boolean automulpkg) {
    // You must log in for the first time
    exec {
        executable = 'java'
        args = ['-jar', rootProject.ext.jiagu["jarPath"].'-login', rootProject.ext.jiagu["name"], rootProject.ext.jiagu["password"]]}// Upgrade to the latest version
    exec {
        executable = 'java'
        args = ['-jar', rootProject.ext.jiagu["jarPath"].'-update']}// Displays the current version number
    exec {
        executable = 'java'
        args = ['-jar', rootProject.ext.jiagu["jarPath"].'-version']}// Import signature information
    exec {
        executable = 'java'
        args = ['-jar', rootProject.ext.jiagu["jarPath"].'-importsign',
                rootProject.ext.signing["storeFile"],
                rootProject.ext.signing["storePassword"],
                rootProject.ext.signing["keyAlias"],
                rootProject.ext.signing["keyPassword"]]}// Hardening is optional
    exec {
        executable = 'java'
        args = ['-jar', rootProject.ext.jiagu["jarPath"].'-config', config]
    }

    // Hardening command
    def jiaGuArgs
    if (automulpkg) {
        jiaGuArgs = ['-jar', rootProject.ext.jiagu["jarPath"].'-jiagu',
                     apkPath,
                     outputPath,
                     '-autosign'.'-automulpkg'.'-pkgparam',
                     rootProject.ext.jiagu["channelConfigPath"]]}else {
        jiaGuArgs = ['-jar', rootProject.ext.jiagu["jarPath"].'-jiagu',
                     apkPath,
                     outputPath,
                     '-autosign'
        ]
    }
    exec {
        executable = 'java'
        args = jiaGuArgs
    }
    println Hardened file path: ${apkPath}
    println Hardened file path: ${outputPath}
}


Run./gradlew releaseApp1 */./gradlew releaseApp1
task releaseApp1(dependsOn: 'assembleApp1OnlineRelease') {
    doFirst {
        // Check whether the hardening program exists. If it does not, download it
        File jarFile = file(rootProject.ext.jiagu["jarPath"])
        if(! jarFile.exists()) { download360jiagu.execute() } } group ="publish"
    doLast {
        File apkOutputFile = new File(APP1_OUTPUT_PATH, getCurTime())
        checkOutputDir(apkOutputFile)
        File apkFile = file(APP1_APK_PATH)
        if(! apkFile.exists()) { println("apk file is not exists:" + apkFile.absolutePath)
            return
        }
        jiaGu("-", apkFile.absolutePath, apkOutputFile.absolutePath, true)}}private static void checkOutputDir(File apkOutputFile) {
    if (apkOutputFile.exists()) {
        File[] files = apkOutputFile.listFiles()
        if(files ! =null) {
            for (File file : files) {
                file.delete()
            }
        }
    } else {
        apkOutputFile.mkdirs()
    }
}


static def getCurTime() {
    return new Date().format("yyyy-MM-dd HH:mm:ss")}Copy the code

Now we just need to execute./gradlew releaseApp1 on the command line and wait for the output.

Create channel.txt in the root jiagu folder where you can configure the multi-channel information you need.

If you need to configure more reinforcement options, can be in jiagu / 360 jiagubao jiagu/help. TXT in view all reinforcement commands.

Reinforcement ultra – tube package upload dandelion

Our supertube package does not need to upload to the app store, but directly upload to dandelion, and then send the QR code to the administrator to download and install. We’ve integrated automatic reinforcement and automatic upload of dandelions.

Jiagu. gradle = jiagu.gradle = jiagu.gradle


def APP1_ADMIN_OUTPUT_PATH = "jiagu/apk/app1Admin/"

def APP1_ADMIN_APK_PATH = "${projectDir.absolutePath}/build/outputs/apk/app1Admin/release/${getApkName(getTestVersionName("The administrator")}"


Run the gradlew jiaGuApp1Admin command./gradlew jiaGuApp1Admin */
task jiaGuApp1Admin(dependsOn: 'assembleApp1AdminRelease') {
    doFirst {
        File jarFile = file(rootProject.ext.jiagu["jarPath"])
        if(! jarFile.exists()) { download360jiagu.execute() } } group ="publish"
    doLast {
        File apkOutputFile = new File(APP1_ADMIN_OUTPUT_PATH)
        checkOutputDir(apkOutputFile)
        File apkFile = file(APP1_ADMIN_APK_PATH)
        if(! apkFile.exists()) { println("apk file is not exists:" + apkFile.absolutePath)
            return
        }
        jiaGu("-", apkFile.absolutePath, apkOutputFile.absolutePath, false)}}Copy the code

Modify dandelion upload method:

def app1AdminFileDir = "${projectDir.parent}/jiagu/apk/app2Admin/"

/** * Run the "uploadApp1Admin" command to automatically upload the super management service package to the dandelion */
task uploadApp1Admin(dependsOn: 'jiaGuApp1Admin') {
    group = "publish"

    doLast {
        File dir = new File(app1AdminFileDir)
        if(! dir.exists()) { println"Alpha dir not exists:" + dir.path
            return
        }
        File[] files = dir.listFiles(new FileFilter() {
            @Override
            boolean accept(File file) {
                return file.isFile() && file.name.endsWith(".apk")}})if (files == null || files.size() == 0) {
            println "files == null || files.size() == 0"
            return
        }
        File apkFile = files[0]

        uploadPGY(apkFile.path)
    }
}
Copy the code

Run./gradlew uploadApp1Admin on the command line to wait for the TWO-DIMENSIONAL code address output.

conclusion

If you don’t like executing command lines, we can also execute automated commands with a click of the mouse:

Demo address: github.com/imliujun/Gr…

reading

  • Improve efficiency – automatically pack and upload dandelions
  • Use Gradle to implement a set of code to develop multiple applications