[Gradle] 如何在android项目中对纯Java module启用proguard

afa0 2019-06-21

如何在android项目中对纯Java module使用release/debug build并启用proguard?这里提供一种方法,尽管不是很“好看”,但是可用。

假设app模块依赖lib模块,lib模块是一个纯Java模块(apply plugin: 'java')。整个过程可以分成两步。

引入Proguard

在lib模块的build.gradle里添加以下代码

import proguard.gradle.ProGuardTask

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'net.sf.proguard:proguard-gradle:5.3.3'
    }
}

task proguardFiles(type: ProGuardTask, dependsOn: compileJava) {
    // 让jar这个task依赖于本task,后文会说明
    tasks.jar.dependsOn.add(proguardFiles)

    println "proguarding"

    // 配置ProGuardTask
    printmapping "$buildDir/mapping.txt"
    configuration 'proguard-rules.pro'
    libraryjars files(configurations.compile.findAll {}.collect())
    injars sourceSets.main.output
    // 设置输出路径,注意这里输出物为文件(不是默认的jar)
    outjars "$buildDir/libs/${project.name}"
    
    // 清除上次的生成物
    delete "$buildDir/libs/${project.name}"

    // 在本task的execute阶段,将混淆后的class文件替换正常class文件
    doLast {
        println "copying product:${sourceSets.main.output.classesDir}"

        // 删除原有的class文件
        delete "${sourceSets.main.output.classesDir}"
        // 将混淆class文件复制过去
        copy {
            from "$buildDir/libs/${project.name}"
            into "${sourceSets.main.output.classesDir}"
        }
    }
}

这里做了几件事情:

  1. 定义proguard task,令jar这个java task依赖于它。即proguard task运行完毕后才运行jar。

  2. 使用文件替换的方式,在jar运行前替换掉class文件。

  3. 通过观察gradle console的输出,得知app在编译时会运行jar task。经过1.2.两步我们可以在正常编译
    流程中插入proguard处理后的class文件。

接下来看怎么样根据debug和release compile关闭或开启proguard

引入debug/release

在lib模块的build.gradle中加入如下代码:

// 定义debug compile的回调函数
void onDebug() {
    println " ----- onDebug ----- "

    // 在debug模式下,关闭混淆优化等一系列操作
    proguardFiles.dontobfuscate()
    proguardFiles.dontoptimize()
    proguardFiles.dontshrink()
    proguardFiles.dontpreverify()
}
// 定义release compile的回调函数
void onRelease() {
    println " ----- onRelease -----"
}

然后在app的build.gradl中加入如下代码:

tasks.whenTaskAdded { task ->
    if (task.name == 'preReleaseBuild') {
        // release build
        task.doLast {
            def taskProject = rootProject.subprojects.findAll {it.name == "lib"}
            taskProject[0].onRelease()
        }
    } else if (task.name == 'preDebugBuild') {
        // debug build
        task.doLast {
            def taskProject = rootProject.subprojects.findAll {it.name == "lib"}
            taskProject[0].onDebug()
        }
    }
}

这段代码做了两个事情:

  1. 监听了task的添加流程,在'preReleaseBuild'和'preDebugBuild'的execute阶段添加了代码逻辑。

  2. 在'preReleaseBuild'和'preDebugBuild'执行完后,执行lib模块中的onRelease或者onDebug方法。

综上,实现了在android项目中对纯Java module使用release/debug build并启用proguard。

注:本文默认读者具有gradle基础知识。
注:附Java Plugin依赖图:
[Gradle] 如何在android项目中对纯Java module启用proguard

相关推荐