首页 > 解决方案 > R8 混淆后接口中 Kotlin 泛型类型参数的问题

问题描述

无法弄清楚如何正确设置 R8 混淆规则以保持我的界面正常工作。

我正在发布一个库。它到处都有混淆代码,除了它是公共 API。

有一个基本接口BaseFoo,在签名中有一个类型参数:

interface BaseFoo<D, E> {
    fun handle(result: SomeOtherClass<D, E>): Boolean
}

然后有一个内部声明Bar了派生接口的类DerivedFoo

class Bar {
    interface DerivedFoo : BaseFoo<Alice, Bob>
}

使用 R8 使用混淆发布此代码后,尝试使用此库的接口DerivedFoo失败:

val myDerivedFoo = object : Bar.DerivedFoo {
    override fun handle(result: SomeOtherClass<Alice, Bob>): Boolean {
        return false
    }
}

object这里显示错误:

对象不是抽象的,不实现抽象成员 public abstract fun handle(result: SomeOtherClass<Alice, Bob>): Boolean defined in com.example.Bar.DerivedFoo

handle方法分别给出了

'handle' 不覆盖任何内容

错误。如果您在此处使用自动完成功能创建一个覆盖函数,您将获得:

override fun handle(result: SomeOtherClass<D, E>): Boolean {
}

那就是 - 完全使用<D, E>泛型参数(而不是<Alice, Bob>),尽管编译器不知道那些DE.

到目前为止,混淆配置设置了以下规则:

-keeppackagenames com.example.**
-keep public class com.example.Bar { *; }
-keep public interface com.example.Bar$DerivedFoo { *; }

# Common rules:
-optimizationpasses 5
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-dontpreverify
-dontshrink
-verbose
-ignorewarnings
-renamesourcefileattribute SourceFile
-keepattributes SourceFile,LineNumberTable,*Annotation*,Signature,InnerClasses,EnclosingMethod,MethodParameters,Exceptions
-keepparameternames
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*,!code/allocation/variable

任何人都可以阐明如何处理这个丢失的派生接口签名吗?

更新:可以在此处找到具有重现问题的示例

标签: kotlinproguardandroid-r8

解决方案


看来配置是正确的,一切都应该工作。但我猜这不是因为一些 Kotlin 互操作性问题。

好消息是,与其他与 Kotlin 相关的问题一起,这已在 2.1.42 版本中得到修复。

所以给定问题的解决方案是强制使用相应的 R8 版本:

buildscript {

    repositories {
        maven {
            url 'https://storage.googleapis.com/r8-releases/raw'
        }
    }

    dependencies {
        classpath 'com.android.tools:r8:2.1.42'          // Must be before the Gradle Plugin for Android.
        classpath 'com.android.tools.build:gradle:X.Y.Z' // Your current AGP version.
     }
}

学分转到这个答案


推荐阅读