You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

开启Gradle的minifyEnabled后无法创建MesResponse类转换器求助

启用minifyEnabled true后Retrofit-Kotlin序列化转换器创建失败问题解决

问题描述

启用混淆后出现以下错误:

java.lang.IllegalArgumentException: Unable to create converter for class com.th3pl4gu3.mes.models.MesResponse
for method MesApiService.getServices

用户相关代码如下:

AppContainer.kt

/**
 * Dependency Injection container at the application level.
 */
interface AppContainer {
    val onlineServiceRepository: ServiceRepository
}

/**
 * Implementation for the Dependency Injection container at the application level.
 *
 * Variables are initialized lazily and the same instance is shared across the whole app.
 */
class DefaultAppContainer(private val context: Context): AppContainer {
    private val BASE_URL = "https://..."

    /**
     * Use the Retrofit builder to build a retrofit object using a kotlinx.serialization converter
     */
    @OptIn(ExperimentalSerializationApi::class)
    private val retrofit: Retrofit = Retrofit.Builder()
        .addConverterFactory(Json.asConverterFactory("application/json".toMediaType()))
        .baseUrl(BASE_URL)
        .build()

    /**
     * Retrofit service object for creating api calls
     */
    private val retrofitService: MesApiService by lazy {
        retrofit.create(MesApiService::class.java)
    }
}

ServiceRepository.kt

/**
 * Repository that fetch service list from Mes API.
 */
interface ServiceRepository {
    /** Fetches list of services from Mes API */
    suspend fun getMesServices(): MesResponse
}

MesApiServiceRepository.kt

class MesApiServiceRepository(

    private val mesApiService: MesApiService

) : ServiceRepository {
    /** Fetches list of Services from Mes API */
    override suspend fun getMesServices(): MesResponse = mesApiService.getServices()
}

MesResponse.kt

@kotlinx.serialization.Serializable
data class MesResponse(
    val services: List<Service>,
    val message: String,
    val success: Boolean
)

proguard-rules.pro

#####################################
########## Kotlin Metadata ##########
#####################################
-dontwarn org.jetbrains.annotations.**
-keep class kotlin.Metadata { *; }

##################################
########### MES Models ###########
##################################
-keep class com.th3pl4gu3.mes.models.MesResponse
-keep class com.th3pl4gu3.mes.models.** {*;}
-keep class com.th3pl4gu3.mes.data.** {*;}
-keep class com.th3pl4gu3.mes.api.** {*;}
-keep class com.th3pl4gu3.mes.di.** {*;}

###############################
########## Retrofit2 ##########
###############################
# Retrofit does reflection on generic parameters. InnerClasses is required to use Signature and
# EnclosingMethod is required to use InnerClasses.
-keepattributes Signature, InnerClasses, EnclosingMethod

# Retrofit does reflection on method and parameter annotations.
-keepattributes RuntimeVisibleAnnotations, RuntimeVisibleParameterAnnotations

# Keep annotation default values (e.g., retrofit2.http.Field.encoded).
-keepattributes AnnotationDefault

# Retain service method parameters when optimizing.
-keepclassmembers,allowshrinking,allowobfuscation interface * {
    @retrofit2.http.* <methods>;
}

# Ignore annotation used for build tooling.
-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement

# Ignore JSR 305 annotations for embedding nullability information.
-dontwarn javax.annotation.**

# Guarded by a NoClassDefFoundError try/catch and only used when on the classpath.
-dontwarn kotlin.Unit

# Top-level functions that can only be used by Kotlin.
-dontwarn retrofit2.KotlinExtensions
-dontwarn retrofit2.KotlinExtensions$*

# With R8 full mode, it sees no subtypes of Retrofit interfaces since they are created with a Proxy
# and replaces all potential values with null. Explicitly keeping the interfaces prevents this.
-if interface * { @retrofit2.http.* <methods>; }
-keep,allowobfuscation interface <1>

# Keep inherited services.
-if interface * { @retrofit2.http.* <methods>; }
-keep,allowobfuscation interface * extends <1>

# 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

解决方案

问题根源是R8/ProGuard在混淆过程中移除了Kotlin序列化所需的注解元数据和相关类,导致Retrofit无法创建对应的转换器。需要更新proguard-rules.pro,添加以下规则:

# 保留Kotlin序列化核心类与注解
-keep class kotlinx.serialization.** { *; }
-dontwarn kotlinx.serialization.**

# 保留所有带@Serializable注解的类及其成员,确保序列化元数据不丢失
-keep @kotlinx.serialization.Serializable class ** {
    *;
}

# 保留序列化器的生成方法(默认序列化器依赖这些方法)
-keepclassmembers class ** {
    @kotlinx.serialization.Serializer <methods>;
}

# 确保序列化所需的注解属性被保留
-keepattributes RuntimeVisibleAnnotations, AnnotationDefault, InnerClasses, Signature

补充说明

  1. 原规则中仅保留了models类,但未保留@Serializable注解以及Kotlin序列化库的核心组件,这些是序列化转换器工作的关键。
  2. 如果使用的是R8 full mode,确保上述规则完全覆盖序列化相关的保留逻辑,避免元数据被剥离。
  3. 验证依赖中已正确引入kotlinx-serialization-json库,版本与Kotlin版本保持兼容。

内容的提问来源于stack exchange,提问作者Mervin Hemaraju

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 00:10:47