天天看点

使用AndroidStudio的Gradle打混淆jar包和aar包

生成混淆jar:

import com.android.build.gradle.LibraryPlugin
import com.android.build.gradle.AppPlugin

def getPackageName(){
    //输出AndroidManifes.xml文件的路径
    println("siy-minifest:"+android.sourceSets.main.manifest.srcFile)
    def androidManifest = new XmlSlurper().parse(android.sourceSets.main.manifest.srcFile)
    def packageName = androidManifest['@package'];
    println("siy-packageName:"+packageName);
    return packageName;
}


def packageNameToPackagePath(){
    String packagePath =  "${getPackageName()}".replace('.','\\');
    println("siy-packagePath:"+packagePath);
    return packagePath;
}


task makeJar(dependsOn: ['compileReleaseJavaWithJavac'], type: Jar) {
    group "payeco"
    description  "Automatically generate the jar packages for the SDK"
    //需打包的资源所在的路径集
    def srcClassDir = [project.buildDir.absolutePath + "\\intermediates\\classes\\release"];
    //初始化资源路径集
    from srcClassDir
    //输出class文件的路径
    println("siy-srcClassDir:"+srcClassDir)
    //去除路径集下部分的资源
    exclude packageNameToPackagePath()+"\\BuildConfig.class"
    //这里需要改为自己的包名,需要将包名aa.bb.cc改成aa\bb\cc
    exclude packageNameToPackagePath()+"\\BuildConfig\$*.class"
    exclude "**\\R.class"
    exclude "**\\R\$*.class"
    //只导入资源路径集下的部分资源
    include packageNameToPackagePath()+"\\**\\*.class"


    //整理输出的 Jar 文件后缀名
    extension = "jar"
    //最终的 Jar 文件名......如果没设置,默认为 [baseName]-[appendix]-[version]-[classifier].[extension]
    archiveName = project.name+"-org-"+android.defaultConfig.versionName+"."+extension
}

task proguardJar(dependsOn: ['makeJar'], type: proguard.gradle.ProGuardTask) {
    group "payeco"
    description  "Automatically generate the proguard jar packages for the SDK"
    //Android 默认的 proguard 文件
    configuration android.getDefaultProguardFile('proguard-android.txt')
    //混淆的配置文件,我的是叫 proguard.cfg,也许有人叫 proguard-project.txt
    configuration 'proguard-rules.pro'
    String inJar = makeJar.archivePath.getAbsolutePath()
    //输入未混淆jar包的路径
    println("siy-inJar:"+inJar)
    //输入 jar
    injars inJar
    //输出 jar
    String outJar = inJar.substring(0, inJar.lastIndexOf(File.separator)) + "\\${makeJar.archiveName}".replace("-org-","-")
    //输出混淆jar包的路径
    println("siy-outJar:"+outJar)
    outjars outJar
    //设置不删除未引用的资源(类,方法等)
    dontshrink


    Plugin plugin = getPlugins().hasPlugin(AppPlugin) ?
            getPlugins().findPlugin(AppPlugin) :
            getPlugins().findPlugin(LibraryPlugin)
    if (plugin != null) {
        List<String> runtimeJarList
        if (plugin.getMetaClass().getMetaMethod("getRuntimeJarList")) {
            runtimeJarList = plugin.getRuntimeJarList()
        } else if (android.getMetaClass().getMetaMethod("getBootClasspath")) {
            runtimeJarList = android.getBootClasspath()
        } else {
            runtimeJarList = plugin.getBootClasspath()
        }
        for (String runtimeJar : runtimeJarList) {
            println("siy-runtimejar:"+runtimeJar)
            //给 proguard 添加 runtime
            libraryjars(runtimeJar)
        }
    }
}
           

这里我解释一下返回包名和将包名的"."替换成"/"这两个方法,我们都知道AS把Java代码编译之后的.class存放在build/intermediates/classes/release下面的,具体路径就应该是build/intermediates/classes/release/packageName下面,所以我需要去manifest下面去读packName,为什么不读build.gradle中的applicationId(如果是一个library中有applicationId吗?),还有一点就是在manifest中读取的packageName是com.a.b.c这样的,所以我又写了一个方法把它变成com/a/b/c这样。如果不想混淆jar,就不需要执行proguarJar这个task.最终生成的jar包在build/libs目录下。

生成混淆的aar:

    buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }


    //更改生成的aar包的名称
    libraryVariants.all{
        variant->
            variant.outputs.each{
                outFile->
                    if(outFile.outputFile !=null && outFile.outputFile.name.endsWith('.aar'))
                        if('release'.equals(variant.buildType.name)) {
                            outFile.outputFile = new File(outFile.outputFile.getParent(), "${project.name}-${android.defaultConfig.versionName}.aar")
                        }else if('debug'.equals(variant.buildType.name)){
                            outFile.outputFile = new File(outFile.outputFile.getParent(), "${project.name}-org-${android.defaultConfig.versionName}.aar")
                        }
            }
    }
           

如果不想要混淆把minifyEnable设置成false就行了。友情提示:如果想要调试module Library最好把buildTypes注释掉。

最终生成的aar包在build/outputs/aar目录下。