Retrofit 迁移到 Android Gradle Plugin (AGP) 8.0 和 Java 17 时出现 Android 混淆问题

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

问题

我在从 Android Gradle Plugin (AGP) 7.4.2 迁移到 8.0 以及 Java 11 迁移到 17 时遇到混淆问题:

Unable to create @Body converter for class package.api.data.device.DevicesBody (parameter #1) for method a.a

除了 API 调用之外,一切都运行良好。我将 Retrofit 2 与 Kotlin 序列化 (kotlinx.serialization) 结合使用。

// Retrofit
implementation "com.squareup.retrofit2:retrofit:2.9.0" // Retrofit
implementation "com.squareup.okhttp3:logging-interceptor:5.0.0-alpha.2" // OkHttp Logging Interceptor

// Kotlin Serialization
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.1" // Kotlin Serialization JSON
implementation "com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:0.8.0" // Retrofit 2 Kotlin Serialization Converter

它可以禁用混淆

minifyEnabled false
或添加混淆规则
-keep class ** { *; }
,但这当然不是一个可接受的解决方案。

我的代码

private val json = kotlinx.serialization.json.Json {
    prettyPrint = true
    ignoreUnknownKeys = true
    explicitNulls = false
}
private val contentType =  "application/json".toMediaType()
private val retrofit: Retrofit by lazy {
    Retrofit.Builder()
        .addConverterFactory(json.asConverterFactory(contentType))
        .baseUrl(baseUrl)
        .client(httpClient)
        .build()
}

@Keep
@Serializable
data class DevicesBody(
    @SerialName("dh_info")
    val dhInfo: DhInfo
)

@Keep
@Serializable
data class DhInfo(
    @SerialName("type")
    val type: String,
    @SerialName("value")
    val value: String
)

@POST("devices")
suspend fun postDevice(@Body requestBody: DevicesBody): Response<DevicesResponse>

例外情况

MESSAGE: Unable to create @Body converter for class {my_package}.api.data.device.DevicesBody (parameter #1) for method a.a
STACKTRACE:
    [retrofit2.Utils.methodError(Utils.java:54),
    retrofit2.Utils.parameterError(Utils.java:60),
    retrofit2.RequestFactory$Builder.parseParameterAnnotation(RequestFactory.java:781),
    retrofit2.RequestFactory$Builder.parseParameter(RequestFactory.java:325),
    retrofit2.RequestFactory$Builder.build(RequestFactory.java:206),
    retrofit2.RequestFactory.parseAnnotations(RequestFactory.java:67),
    retrofit2.ServiceMethod.parseAnnotations(ServiceMethod.java:26),
    retrofit2.Retrofit.loadServiceMethod(Retrofit.java:202),
    retrofit2.Retrofit$1.invoke(Retrofit.java:160),
    java.lang.reflect.Proxy.invoke(Proxy.java:1006),
    $Proxy5.a(Unknown Source), g0.j0.invokeSuspend(SourceFile:1),
    g0.j0.invoke(SourceFile:1), c.g.a(SourceFile:0),
    g0.k0.invokeSuspend(SourceFile:0),
    g0.k0.invoke(SourceFile:1),
    kotlinx.coroutines.flow.SafeFlow.collectSafely(Builders.kt:61),
    kotlinx.coroutines.flow.AbstractFlow.collect(Flow.kt:230),

AGP 8.0 的更改

为了迁移到 Android Gradle Plugin (AGP) 8.0(包括 Java 17),我进行了以下更改:

  • app/build.gradle

    dependencies {
        classpath "com.android.tools.build:gradle:8.0.2"
    }
    
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_17
        targetCompatibility JavaVersion.VERSION_17
    }
    
    kotlinOptions {
        jvmTarget = '17'
    }

  • gradle-wrapper.properties
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip
  • gradle.properties
# Enable generation of the BuildConfig class
android.defaults.buildfeatures.buildconfig=true
# Disable on-transitive R classes
android.nonTransitiveRClass=false
# Disable R classes with non-final fields
android.nonFinalResIds=false
  • app/proguard-rules.pro
# Keep generic signature of Call, Response (R8 full mode strips signatures from non-kept items).
-keep,allowobfuscation,allowshrinking interface retrofit2.Call
-keep,allowobfuscation,allowshrinking class retrofit2.Response

# With R8 full mode generic signatures are stripped for classes that are not
# kept. Suspend functions are wrapped in continuations where the type argument
# is used.
-keep,allowobfuscation,allowshrinking class kotlin.coroutines.Continuation

解决方案

proguard-rules.pro

...
# API data package (for Retrofit2)
-keep class {my_package}.api.data.** { *; }
-keep public enum {my_package}.api.data.** { *; }
...
# Retrofit2
# Keep generic signature of Call, Response (R8 full mode strips signatures from non-kept items).
-keep,allowobfuscation,allowshrinking interface retrofit2.Call
-keep,allowobfuscation,allowshrinking class retrofit2.Response
# With R8 full mode generic signatures are stripped for classes that are not kept. Suspend functions
# are wrapped in continuations where the type argument is used.
-keep,allowobfuscation,allowshrinking class kotlin.coroutines.Continuation
android gradle proguard obfuscation android-r8
1个回答
0
投票

似乎存在兼容性问题。您使用的改造版本不支持 Gradle 8.0。 根据 Retrofit 的 Github 存储库上的信息,他们支持的最新 Gradle 版本是7.6.2,这是 5 天前完成的。不过,Retrofit 2.9.0 版本已于 2020 年发布。我相信未来几个月将会发布新版本。

© www.soinside.com 2019 - 2024. All rights reserved.