忽略外部库的混淆器配置

问题描述 投票:0回答:3

所以,我想向我的项目添加一个外部库。库本身很小,大约有 300 个方法。但它的 proguard 配置被配置得非常自由。我在一个准系统项目上运行了一个简单的测试,有/没有库,有/没有 proguard,这就是我想出的

Proguard    Lib     Method Count
N           N       15631
Y           N       6370
N           Y       15945
Y           Y       15573

如您所见,启用 proguard 后,计数约为 6000。但是当我添加库时,尽管库本身只有约 300 个方法,但计数猛增至约 15000 个。

所以我的问题是,如何忽略这个特定库的混淆器配置?

更新:

现在用android gradle插件是不可能的。我发现 android bug 根本没有优先级。请避免在回答中提到“这是不可能的”,并保持问题的开放性,直到找到解决方法或做出正式决定为止。否则,您将获得一半的赏金,而不会增加任何价值。谢谢!

android gradle android-gradle-plugin proguard
3个回答
11
投票

在这种特定情况下,您有几种选择:

  • 从aar中提取classes.jar文件并将其作为正常的jar依赖项包含在项目中(当aar包含资源时将不起作用)
  • 更改 aar 并从中删除消费者混淆规则
  • 使用DexGuard,它可以让您过滤掉不需要的消费者规则
  • 做一些 gradle hacking,见下文

将以下内容添加到您的 build.gradle 中:

afterEvaluate {
  // All proguard tasks shall depend on our filter task
  def proguardTasks = tasks.findAll { task ->
    task.name.startsWith('transformClassesAndResourcesWithProguardFor') }
  proguardTasks.each { task -> task.dependsOn filterConsumerRules }
}

// Let's define our custom task that filters some unwanted
// consumer proguard rules
task(filterConsumerRules) << {
  // Collect all consumer rules first
  FileTree allConsumerRules = fileTree(dir: 'build/intermediates/exploded-aar',
                                       include: '**/proguard.txt')

  // Now filter the ones we want to exclude:
  // Change it to fit your needs, replace library with
  // the name of the aar you want to filter.
  FileTree excludeRules = allConsumerRules.matching {
    include '**/library/**'
  }

  // Print some info and delete the file, so ProGuard
  // does not pick it up. We could also just rename it.
  excludeRules.each { File file ->
    println 'Deleting ProGuard consumer rule ' + file
    file.delete()
  }
}

使用 DexGuard (7.2.02+) 时,您可以将以下代码片段添加到 build.gradle 中:

dexguard {
  // Replace library with the name of the aar you want to filter
  // The ** at the end will include every other rule.
  consumerRuleFilter '!**/library/**,**'
}

请注意,逻辑与上面的 ProGuard 示例相反,consumerRuleFilter 将仅包含与模式匹配的消费者规则。


3
投票

如果您使用 R8(自 Android Gradle 插件 3.4.0 起取代了 ProGuard) - 您可以通过将以下解决方法添加到模块的

build.gradle
:

来过滤掉特定的消费者规则文件
tasks.whenTaskAdded { Task task ->
    // Once 'minifyEnabled' is set to 'true' for a certain build type/variant - 
    // a 'minify<variantName>WithR8' task will be created for each such variant
    //
    // - This task is implemented by com.android.build.gradle.internal.tasks.R8Task
    // - R8Task extends from ProguardConfigurableTask
    // - ProguardConfigurableTask exposes property 'configurationFiles'
    // - configurationFiles contains all files that will be contributing R8 rules
    // - configurationFiles is mutable (its type is ConfigurableFileCollection)
    //
    // Thus - we can overwrite the list of files and filter them out as we please
    //
    // More details: https://cs.android.com/android-studio/platform/tools/base/+/mirror-goog-studio-main:build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/R8Task.kt
    if (task.name.startsWith("minify") && task.name.endsWith("WithR8")) {
        afterEvaluate {
            def filteredList = task.configurationFiles.filter {
                // Example paths in this collection:
                // /Users/me/MyProject/myModule/proguard-rules.pro
                // (for library dependencies) /Users/me/.gradle/caches/<...>/okhttp3.pro

                // The below filter condition will, for example, exclude consumer ProGuard rules file from the AndroidX RecyclerView library
                !it.path.contains("recyclerview-1.1.0")
            }
            task.configurationFiles.setFrom(filteredList.files)
        }
    }
}

上述解决方法已确认适用于 Android Gradle 插件 4.2.2

如果决定依赖这样的解决方法 - 添加某种自动检查和/或测试以确保此过滤有效可能是个好主意。鉴于该解决方案非常脆弱,并且可能会随着 Android Gradle 插件的未来更新而崩溃。


0
投票

编辑:在 Gradle 7.3 中,有一种方法可以指定忽略保留规则的依赖项:https://developer.android.com/reference/tools/gradle-api/7.3/com/android/build/api /dsl/KeepRules#ignoreExternalDependency(kotlin.Array)

例如:

buildTypes {
    release {
        optimization.keepRules {
            it.ignoreExternalDependencies("androidx.lifecycle:lifecycle-runtime")
        }
    }
}

旧答案:受到 Jonas 答案的启发,针对 Kotlin DSL 进行了修改,并确认在 Android Gradle 插件 7.2.1 上工作:

import com.android.build.gradle.internal.tasks.ProguardConfigurableTask

afterEvaluate {
    // Get each ProguardConfigurableTask
    tasks.withType(ProguardConfigurableTask::class.java).forEach { task ->
        // Remove proguard rules from lifecycle-runtime library
        val filteredConfigurationFiles = task.configurationFiles.filter { file ->
            !file.path.contains("lifecycle-runtime")
        }
        task.configurationFiles.setFrom(filteredConfigurationFiles)
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.