【android应用】gradle编译时应用版本号自动生成和裁剪库文件(build.grade)

最近在弄android应用,不可避免的要涉及到版本号的问题,还需要定制化库,删除某些不需要到库文件,裁剪apk的大小。本篇就是记录一下版本号自动生成问题和裁剪库文件的解决方案。


一、命名规则

本文采取一下命名规则。

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    android:versionName="aa.bb.cccc.yymmdd.xxxxx"
    android:versionCode="aabbcccc"
    package="com.example.xxx">

说明:

  • aa是大版本号,bb是小版本号,最多2位,不足不补0。
  • cccc是Git库的提交次数,xxxxx是Git库HEAD的SHA1码前5位。
  • yymmdd是日期,yy是年的后两位,mm是月,dd是日,不足补0。

二、编译脚本build.gradle中实现自动生成版本号

根据git信息自动生成版本号,命令如下:

git rev-list --count HEAD # This is cccc
git describe --always # This is short SHA1

在build.gradle文件中的defaultconfig写入规则versionCode getSelfDefinedVersion()获取

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.3"

    defaultConfig {
        applicationId "com.example.xxx"
        minSdkVersion 22
        targetSdkVersion 23
        versionCode getSelfDefinedVersion("code")
        versionName getSelfDefinedVersion("name")
    }
    buildTypes {
        release {
            minifyEnabled false
        }
    }
}

在build.gradle文件文件中实现函数getSelfDefinedVersion(),大小版本号通过传参方式传入。

def getTinkerVersionValue(type) {
    if ("big".equals(type)) {
        return hasProperty("APP_BIG_VERSION") ? APP_BIG_VERSION : "2"
    } else if ("small".equals(type)) {
        return hasProperty("APP_SMALL_VERSION") ? APP_SMALL_VERSION : "0"
    }
}

def getSelfDefinedVersion(type) {
    int aa = getTinkerVersionValue("big").toInteger()  //大版本号
    int bb = getTinkerVersionValue("small").toInteger()  //小版本号

    printf("getversion version : $aa.$bb \n")

    Process process = "git rev-list --count HEAD".execute()
    process.waitFor()
    int cccc = process.getText().toInteger()

    if ("code".equals(type)) {
        aa * 1000000 + bb * 10000 + cccc
    } else if ("name".equals(type)) {
        String today = new Date().format("yyMMdd")
        process = "git describe --always".execute()
        process.waitFor()
        String sha1 = process.getText().trim()
        "$aa.$bb.$cccc.$today.$sha1"
    }
}

三、编译测试

gradlew assembleJUMPRelease -PAPP_BIG_VERSION=2 -PAPP_SMALL_VERSION=1

有两个版本号是因为在system/app下面有一个apk,本次安装是在data/app目录下的。

四、裁剪库文件

我编写了一个task,在即将打包时,把正常的so文件删除多余的so文件

def getTinkeChannelValue() {
    return hasProperty("CHANNEL") ? CHANNEL : "TEST"
}

task clearLibs() {
    doLast{
        def channel = getTinkeChannelValue()
        println "-------clear some libs------"
        if ("TEST".equals(getTinkeChannelValue())) {
            def dir = new File("build/intermediates/transforms/")
            fileTree(dir).each { file ->
                if("libijkffmpeg.so".equals(file.name)||"libijkplayer.so".equals(file.name)||"libijksdl.so".equals(file.name)){
                    delete file.path
                    println file.path
                }
            }
        }
    }
}

afterEvaluate {
    tasks.matching {
        it.name.startsWith('process') && (it.name.endsWith('ReleaseJavaRes') || it.name.endsWith
                ('DebugJavaRes'))
    }.each { tk ->
        tk.dependsOn(clearLibs)
    }
}

实现了clearLibs先于以process开头以ReleaseJavaRes或DebugJavaRes结尾的标准task执行(当然还可以写成it.name.equals(***),语法类似Java)。

五、整个build.grade文件源码

apply plugin: 'com.android.application'

String getManifestPath() {
    def channel = getTinkeChannelValue()
    if("TEST".equals(channel)){
        return "src/main/AndroidManifestTEST.xml"
    }
    return "src/main/AndroidManifest.xml"
}

def getTinkeChannelValue() {
    return hasProperty("CHANNEL") ? CHANNEL : "TEST"
}

def getTinkerVersionValue(type) {
    if ("big".equals(type)) {
        return hasProperty("APP_BIG_VERSION") ? APP_BIG_VERSION : "2"
    } else if ("small".equals(type)) {
        return hasProperty("APP_SMALL_VERSION") ? APP_SMALL_VERSION : "0"
    }
}

def getSelfDefinedVersion(type) {
    int aa = getTinkerVersionValue("big").toInteger()  //大版本号
    int bb = getTinkerVersionValue("small").toInteger()  //小版本号

    printf("getversion version : $aa.$bb \n")

    Process process = "git rev-list --count HEAD".execute()
    process.waitFor()
    int cccc = process.getText().toInteger()

    if ("code".equals(type)) {
        aa * 1000000 + bb * 10000 + cccc
    } else if ("name".equals(type)) {
        String today = new Date().format("yyMMdd")
        process = "git describe --always".execute()
        process.waitFor()
        String sha1 = process.getText().trim()
        "$aa.$bb.$cccc.$today.$sha1"
    }
}

android {
    ... ...
    defaultConfig {
        ... ...
        versionCode getSelfDefinedVersion("code")
        versionName getSelfDefinedVersion("name")
        ... ...
    }
    ... ...

    sourceSets {
        main {
            manifest.srcFile getManifestPath()
        }
    }

    applicationVariants.all { variant ->
        variant.outputs[0].processManifestProvider.get().doLast {
            //渠道与配置名
            String variantName = variant.name.capitalize()
            //写死为JUMP_COMMON以后该渠道号,需要一起改掉
            //JUMP_COMMON_USER渠道的为普通用户,没有SYSTEM权限
            if (variant.productFlavors[0].name == "JUMP_COMMON_USER") {
                //要替换的manifest文件
                def manifestFile = "${projectDir}${File.separator}build${File.separator}intermediates${File.separator}merged_manifests${File.separator}${variantName}${File.separator}AndroidManifest.xml"

                //源文件
                def srcManifact = "${projectDir}${File.separator}configs${File.separator}${variant.productFlavors[0].name}.xml"

                //通过源文件内容替换
                def updatedContent = new File(srcManifact).getText('UTF-8')
                new File(manifestFile).write(updatedContent, 'UTF-8')
            }
        }
    }

    productFlavors {
        ... ...
    }

    productFlavors.all {
        flavor -> flavor.manifestPlaceholders = [CHANNEL_VALUE: name]
    }
}

dependencies {
    ... ...
}

task clearLibs() {
    doLast{
        def channel = getTinkeChannelValue()
        println "-------clear some libs------"
        if ("TEST".equals(getTinkeChannelValue())) {
            def dir = new File("build/intermediates/transforms/")
            fileTree(dir).each { file ->
                if("libijkffmpeg.so".equals(file.name)||"libijkplayer.so".equals(file.name)||"libijksdl.so".equals(file.name)){
                    delete file.path
                    println file.path
                }
            }
        }
    }
}

afterEvaluate {
    tasks.matching {
        it.name.startsWith('process') && (it.name.endsWith('ReleaseJavaRes') || it.name.endsWith
                ('DebugJavaRes'))
    }.each { tk ->
        tk.dependsOn(clearLibs)
    }
}

结束语

以上就是本次分享的android应用开发中,gradle编译时应用版本号自动生成和裁剪库文件(build.grade)。最后惯例给大家推介一下我们的技术工作号,欢迎大家来交流技术问题,谢谢!

在这里插入图片描述

发布了61 篇原创文章 · 获赞 45 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/twk121109281/article/details/103061888
今日推荐