Gradle +VasDolly:实现命令行输出任意渠道包

前言

如果你还不知道什么是VasDolly,那么建议你先点击这里看看

如果你还不知道怎样在项目中集成VasDolly,那么建议你先看看我上一篇文章 《Gradle配合 VasDolly进行多渠道打包,让打包效率飞起来》

背景

在上一篇文章中,我们已经成功的在项目中集成了VasDolly了,每次要打包多个渠道版本的时候,我们只需要在Gradle Task中选择对应的Task,一键下去就可以快速生成多个渠道包,真的是省时又省力,爽歪歪呀~

但是市场信息瞬息万变,运营的需求也是越来的随心所欲。没办法,我司的程序猿作为公司的最底层,基本谁都可以随时怼个需求过来,然后末了还加上一句:这是个价值10w的需求,怎么实现我不管,有问题可以找老板!

所以面对运营的同事经常临时的跟一些奇奇怪怪的推广公司合作的时候,总会突然就要求程序猿临时 输出一些特殊的渠道包(也就是一次性的应用渠道包,只提供给这次的推广合作对象)。然后配合一些第三方的统计工具,就可以统计到对方给我们带来多少的下载,带来多少新户激活,然后进行推广费用结算等等。

所以一个能够 随时输出 任意渠道包的task是很重要的。关键的时候能省下很多的事儿。

刚好,VasDolly就有这样的特性。只需要简单的配置就行。

其实

因为 VasDolly 从v2.0.0开始支持添加渠道参数:gradle channelDebug -Pchannels=yingyongbao,gamecenter,这里通过属性channels指定的渠道列表拥有更高的优先级,且和原始的文件方式是互斥的。

所以其实可以直接在终端 使用命令行输出渠道包:

gradle  channelRelease -Pchannels=test1,test2 
 //或者输出测试包
gradle  channelDebug -Pchannels=test1,test2

但是为了后续的可定制化,以及统一化,我们可以自己编写task (因为后续系列的文章会写到 多应用打包、即马甲包。以及如何在执行打包完之后自动加固,并下载回来重新签名Apk。以及如何在所有的Apk都生成之后自动上传到指定的阿里云oss或者七牛云存储)所以如果对后续的文章要是感兴趣就请继续往下看,先对怎样自定义gradle task等等有个基本的概念。

准备

作为一只成熟的程序猿,都必须掌握一项基本的技能:git 版本控制(不知道什么是 git 的请点这里)

在日常的开发中,我们都要养成一个好的习惯,即要维护一个稳定的release版本分支,同时要有一个作为开发的dev分支。

这个是最基本的要求。

如果项目有大的变动,而且这个变动也不确定最终是否采用,那最好也要切一个分支出来,称为实验性的分支。

这主要解决什么问题呢?

假设我们已经发布的App 1.0版本都一个多星期了,程序猿早就进行V1.1版本需求的开发了,这时候要是运营小姐姐说她要一个V1.0的新渠道包,那岂不是要跪。一般进行代码回滚的坑都很多的。所以这时候有个稳定的分支,然后日常的开发只需要在dev分支上进行,这样要编译生成新的渠道包的时候只需要我把dev的代码commit一下之后切到稳定版master分支,不就可以无缝的切过来了~(其实最建议的还是做一个jenkins进行集成化发布,这个在后续的文章会讲)。

那么现在假设你已经有了良好的开发习惯并实习的掌握的git,以及也已经成功的集成了VasDolly

开始编写Gradle 文件

在项目的我们新建一个 gradle文件,就先命名为gradle2market.gradle

image

把新建的Gradle文件跟项目进行关联起来

我在app下的build.gradle文件末尾添加一句

applyfrom:rootProject.file('Gradle2Market.gradle')

image

开始进行在Gradle2Market.gradle 脚本的编写

直接 发布具体代码:

/**
 * 为市场推广同事做的Jenkins动态构建渠道包
 * - Jenkins中输入渠道信息
 * - 不支持加固(一定要注意),如果实在有加固的需求,以后有时间再做
 * @author Eason
 */


/**
 * 在命令行中取回marketchannel的参数
 * @return
 */
String getCommandLineChannel() {
    if (project.hasProperty("marketChannel")) {
        return project.marketChannel
    } else if (getDebug() == 'true') {
        return "test"
    }
    return ""
}

/**
 * 在命令行获取debug参数
 * 代表是否编译测试版
 * @return
 */
String getDebug() {
    if (project.hasProperty("debug")) {
        return project.debug
    }
    return false
}

/**
 * 组装对应的编译命令
 * @return
 */
String getCurrentAppBuildCommand() {
    def commandStr = "channel"
    if (getDebug() == 'true') {
        commandStr = commandStr + "Debug"
    } else {
        commandStr = commandStr + "Release"
    }
    return commandStr
}
/**
 * 返回对应的编译包存放地址
 * @return
 */
String getCurrentBuildDir() {
    def fileDir = "/channelRoot/test/"
    if (getDebug() == 'true') {
        fileDir = fileDir + "/debug"
    } else {
        fileDir = fileDir + "/release"
    }
    return "${project.buildDir}" + fileDir
}

/**
 * 根据命令行传入的渠道信息,动态构建渠道包
 */
task buildChannelApk(type: Exec) {
    doFirst {
        def channel = getCommandLineChannel()
        println "校验渠道信息 输入的渠道信息为:channel = ${channel} fileDir = ${getCurrentBuildDir()} ===================>>>>"
        if (channel == null || channel.length() == 0) {
            if (getDebug() == 'true') {
                channel = "test"
            } else {
                throw new GradleException("请传入正确的渠道信息,以英文逗号分隔")
            }
        }
    }
    group = "market" // 给当前的task分组,编译后可以在gradle task中看到 market目录
    description = "根据命令行传入的渠道信息,动态构建渠道包"

    workingDir "${rootProject.projectDir}"

    if (org.gradle.internal.os.OperatingSystem.current() == org.gradle.internal.os.OperatingSystem.WINDOWS) {
        //windows
        commandLine 'cmd', '/k', 'gradlew -Dorg.gradle.jvmargs=-Xmx1536m', '-Dfile.encoding=UTF-8', "-Pchannels=${getCommandLineChannel()}", "-Pdebug=${getDebug()}", "${getCurrentAppBuildCommand()}"
    } else { //linux ,macos
        commandLine 'gradlew', '-Dorg.gradle.jvmargs=-Xmx1536m', '-Dfile.encoding=UTF-8', "-Pchannels=${getCommandLineChannel()}", "-Pdebug=${getDebug()}", "${getCurrentAppBuildCommand()}"
    }

    doLast {
        println "渠道包已构建完毕.  输入的渠道信息为:{${getCommandLineChannel()}} debug=${getDebug()} ===================>>>>"
    }
}

主要的功能在都在代码的备注中写的很详细了。
然后rebuild项目,完成之后就可以在gradle task看到新生成的task了

image.png

我们在终端就可以直接输入命令行执行编译了 (debug参数不传 默认是false),


image.png

image.png

然后在对应的文件夹就可以看到编译好的Apk


image.png

最后

此时,如果运营的同事跟你说要一个 V1.0版本的 xiaomi 渠道包,你就可以优雅的切到master分支,然后在终端输入 :

gradle buildChannelApk -PmarketChannel=xiaomi

然后坐等编译完成就OK了~

看到这里,基本你应该了解:

1.如何创建一个gradle文件并于项目关联起来
2.如何从命令行中获取一个参数的输入 (例如 marketChannel 参数)
3.如何定义一个task (buildChannelApk函数 )
4.如何使用一个 task

如果这时候你公司的运维同事已经为你搭建好jenkins持续集成环境的话,那么你的项目已经可以实现配置在jenkins上,让运营自己随时打包了。


image.png

Demo

点击这里查看demo

如果觉得文章对你有用,请点个赞吧~

你可能感兴趣的:(Gradle +VasDolly:实现命令行输出任意渠道包)