天天看點

使用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目錄下。