如何使用 Kotlin 为 Android 版本构建配置 ProGuard

Posted

技术标签:

【中文标题】如何使用 Kotlin 为 Android 版本构建配置 ProGuard【英文标题】:How to configure ProGuard for an Android release build with Kotlin 【发布时间】:2019-04-02 19:28:05 【问题描述】:

我将 Kotlin 1.2.71 添加到我的 android (Java) 应用程序项目中。 该项目是为 Java 8 配置的:

compileOptions 
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8

以下是 Kotlin 的变化:

classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.2.71"

...

apply plugin: "kotlin-android"
apply plugin: "kotlin-android-extensions"
apply plugin: "kotlin-kapt"

...

implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.2.71"
kapt "org.parceler:parceler:1.1.11"

我注意到使用 ProGuard 的发布构建失败。构建过程输出以下信息:

Warning: kotlin.internal.jdk8.JDK8PlatformImplementations: can't find referenced 
    method 'int start(java.lang.String)' in library class java.util.regex.Matcher
Warning: kotlin.internal.jdk8.JDK8PlatformImplementations: can't find referenced 
    method 'int end(java.lang.String)' in library class java.util.regex.Matcher
Warning: kotlin.internal.jdk8.JDK8PlatformImplementations: can't find referenced 
    method 'java.lang.String group(java.lang.String)' in library class java.util.regex.Matcher

Note: kotlin.internal.PlatformImplementationsKt: can't find dynamically 
    referenced class kotlin.internal.JRE8PlatformImplementations
Note: kotlin.internal.PlatformImplementationsKt: can't find dynamically 
    referenced class kotlin.internal.JRE7PlatformImplementations
Note: kotlin.jvm.internal.Reflection: can't find dynamically 
    referenced class kotlin.reflect.jvm.internal.ReflectionFactoryImpl

Note: the configuration keeps the entry point 
    'com.google.android.gms.flags.impl.FlagProviderImpl  void init(com.google.android.gms.dynamic.zzd); ', 
    but not the descriptor class 'com.google.android.gms.dynamic.zzd'

Note: there were 1 unkept descriptor classes in kept class members.
      You should consider explicitly keeping the mentioned classes
      (using '-keep').
      (http://proguard.sourceforge.net/manual/troubleshooting.html#descriptorclass)
Note: there were 3 unresolved dynamic references to classes or interfaces.
      You should check if you need to specify additional program jars.
      (http://proguard.sourceforge.net/manual/troubleshooting.html#dynamicalclass)
Warning: there were 3 unresolved references to library class members.
         You probably need to update the library versions.
         (http://proguard.sourceforge.net/manual/troubleshooting.html#unresolvedlibraryclassmember)
Warning: Exception while processing task java.io.IOException: Please correct the above warnings first.
Thread(Tasks limiter_9): destruction

据我所知,Kotlin 不需要任何特殊的 ProGuard 规则。 People recommend(2015 年发布)只是简单地说规则:

-dontwarn kotlin.**

这仍然是推荐的解决方案吗?

相关

Kotlin docs: Using Kotlin for Android Development ***: How to use Kotlin with Proguard ProGuard issue #182: Support Kotlin class files KT-7652: Specify and document Proguard rules for kotlin-reflect.jar

【问题讨论】:

不确定在 android 上使用 kotlin-stdlib-jdk8 是个好主意,因为除非您使用 minSdkVersion 24,否则无法完全支持 jdk8 类,请参阅 developer.android.com/studio/write/java8-support - 您的错误看起来可能是问题。试试kotlin-stdlib-jdk7 这应该不是问题,因为我在 build.gradle 配置中也使用了 compileOptions sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 那是不同的东西。 android 构建使用工具将 java 8 语法/类文件转换为 java7 或更低(android)的 dex 文件。请参阅上面的链接在哪个 api 级别上可用。该工具无法模拟该 API 级别中不存在的方法。例如,它可以模拟 lambdas。 对不起我的骄傲。使用kotlin-stdlib-jdk7 实际上可以让发布构建成功。谢谢! 【参考方案1】:

查看实际警告告诉您它在 java 标准库中找不到特定方法。

引用Matcher.end(String) 表明它是一种仅在您的minSdk 为26 时可用的方法。这是添加 Java-8 支持时的 SDK 级别。

简单地说,您正在尝试将 java8 级别的 kotlin 库与不支持它的 android sdk 一起使用,从而导致您观察到的错误。

【讨论】:

感谢您的描述性解释!

以上是关于如何使用 Kotlin 为 Android 版本构建配置 ProGuard的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Kotlin 中使用支持库 graddle.app?

Android Compose 版本与 Kotlin 版本的兼容问题

Android Compose 版本与 Kotlin 版本的兼容问题

Android Compose 版本与 Kotlin 版本的兼容问题

Android Compose 版本与 Kotlin 版本的兼容问题

android kotlin multiplatform kotlinx.serialization 适用于调试但不适用于发布版本