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

Google Play预启动报告出现ClassCastException,疑与ProGuard混淆相关

问题说明

最近更新应用后,Google Play预启动报告显示9台测试设备触发java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType异常,堆栈信息指向Retrofit相关方法。未新增第三方库,仅修改了业务代码,怀疑是ProGuard混淆规则缺失导致。

异常堆栈信息

Exception java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType
  at retrofit2.HttpServiceMethod.parseAnnotations (HttpServiceMethod.java:46)
  at retrofit2.ServiceMethod.parseAnnotations (ServiceMethod.java:39)
  at retrofit2.Retrofit.loadServiceMethod (Retrofit.java:202)
  at retrofit2.Retrofit$1.invoke (Retrofit.java:160)
  at java.lang.reflect.Proxy.invoke (Proxy.java:1006)
  at $Proxy9.b
  at com.blogspot.abtallaldigital.bloggy.data.RemoteDataSource.getPostListByLabel (RemoteDataSource.java:15)
  at com.blogspot.abtallaldigital.bloggy.viewmodels.PostViewModel.getPostsByLabelSafeCall (MainViewModel.kt:147)
  at com.blogspot.abtallaldigital.bloggy.viewmodels.PostViewModel.access$getPostsByLabelSafeCall (MainViewModel.kt:28)
  at com.blogspot.abtallaldigital.bloggy.viewmodels.PostViewModel$getPostListByLabel$1.invokeSuspend (MainViewModel.kt:127)
  at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith (ContinuationImpl.kt:33)
  at kotlinx.coroutines.DispatchedTask.run (DispatchedTask.kt:106)
  at kotlinx.coroutines.EventLoop.processUnconfinedEvent (EventLoop.java:68)
  at kotlinx.coroutines.internal.DispatchedContinuationKt.resumeCancellableWith (DispatchedContinuation.kt:373)
  at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable (Cancellable.kt:30)
  at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable$default (Cancellable.kt:25)
  at kotlinx.coroutines.CoroutineStart.invoke (CoroutineStart.java:110)
  at kotlinx.coroutines.AbstractCoroutine.start (AbstractCoroutine.kt:126)
  at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch (BuildersKt__Builders_common.kt:56)
  at kotlinx.coroutines.BuildersKt.launch (Builders.kt:1)
  at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch$default (BuildersKt__Builders_common.kt:47)
  at kotlinx.coroutines.BuildersKt.launch$default (Builders.kt:1)
  at androidx.lifecycle.RepeatOnLifecycleKt$repeatOnLifecycle$3$1$1$1.onStateChanged (RepeatOnLifecycle.kt:106)
  at androidx.lifecycle.LifecycleRegistry$ObserverWithState.dispatchEvent (LifecycleRegistry.kt:314)
  at androidx.lifecycle.LifecycleRegistry.forwardPass (LifecycleRegistry.kt:251)
  at androidx.lifecycle.LifecycleRegistry.sync (LifecycleRegistry.kt:287)
  at androidx.lifecycle.LifecycleRegistry.moveToState (LifecycleRegistry.kt:136)
  at androidx.lifecycle.LifecycleRegistry.handleLifecycleEvent (LifecycleRegistry.kt:119)
  at androidx.fragment.app.FragmentViewLifecycleOwner.handleLifecycleEvent (FragmentViewLifecycleOwner.java:100)
  at androidx.fragment.app.Fragment.performStart (Fragment.java:3194)
  at androidx.fragment.app.FragmentStateManager.start (FragmentStateManager.java:628)
  at androidx.fragment.app.FragmentStateManager.moveToExpectedState (FragmentStateManager.java:290)
  at androidx.fragment.app.FragmentManager.executeOpsTogether (FragmentManager.java:1943)
  at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute (FragmentManager.java:1845)
  at androidx.fragment.app.FragmentManager.execPendingActions (FragmentManager.java:1782)
  at androidx.fragment.app.FragmentManager$5.run (FragmentManager.java:565)
  at android.os.Handler.handleCallback (Handler.java:938)
  at android.os.Handler.dispatchMessage (Handler.java:99)
  at androidx.test.espresso.base.Interrogator.loopAndInterrogate (Interrogator.java:10)
  at androidx.test.espresso.base.UiControllerImpl.loopUntil (UiControllerImpl.java:7)
  at androidx.test.espresso.base.UiControllerImpl.loopUntil (UiControllerImpl.java:1)
  at androidx.test.espresso.base.UiControllerImpl.injectMotionEvent (UiControllerImpl.java:5)
  at androidx.test.espresso.action.MotionEvents.sendUp (MotionEvents.java:6)
  at androidx.test.espresso.action.MotionEvents.sendUp (MotionEvents.java:1)
  at androidx.test.espresso.action.Tap.sendSingleTap (Tap.java:5)
  at androidx.test.espresso.action.Tap.-$$Nest$smsendSingleTap
  at androidx.test.espresso.action.Tap$1.sendTap (Tap.java:1)
  at androidx.test.espresso.action.GeneralClickAction.perform (GeneralClickAction.java:4)
  at androidx.test.espresso.ViewInteraction$SingleExecutionViewAction.perform (ViewInteraction.java:2)
  at androidx.test.espresso.ViewInteraction.doPerform (ViewInteraction.java:23)
  at androidx.test.espresso.ViewInteraction.-$$Nest$mdoPerform
  at androidx.test.espresso.ViewInteraction$1.call (ViewInteraction.java:6)
  at androidx.test.espresso.ViewInteraction$1.call (ViewInteraction.java:1)
  at java.util.concurrent.FutureTask.run (FutureTask.java:266)
  at android.os.Handler.handleCallback (Handler.java:938)
  at android.os.Handler.dispatchMessage (Handler.java:99)
  at android.os.Looper.loopOnce (Looper.java:201)
  at android.os.Looper.loop (Looper.java:288)
  at android.app.ActivityThread.main (ActivityThread.java:7839)
  at java.lang.reflect.Method.invoke
  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:548)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1003)

当前ProGuard配置文件

-keep public class com.google.android.gms.ads.** {
        public *;
    }

    -keep public class com.google.ads.** {
         public *;
    }

    -keep class com.google.ads.** # Don't proguard AdMob classes
    -dontwarn com.google.ads.** # Temporary workaround for v6.2.1. It gives a warning that you can ignore

#
#
#-keepclassmembers class * implements java.io.Serializable {
#    private static final java.io.ObjectStreamField[] serialPersistentFields;
#    private void writeObject(java.io.ObjectOutputStream);
#    private void readObject(java.io.ObjectInputStream);
#    java.lang.Object writeReplace();
#    java.lang.Object readResolve();
#}
#
## Lru Cache
#-keep class com.squareup.picasso.LruCache { *; }
#-dontwarn com.squareup.picasso.LruCache.**
#
## Firebase
#-keep class com.firebase.** { *; }
#-dontwarn com.firebase.**
#
#-keepnames class com.shaded.fasterxml.** { *; }
#-dontwarn org.shaded.apache.**
#
#-keep class org.apache.** { *; }
#-dontwarn org.apache.**
#
#-keepnames class org.ietf.jgss.** { *; }
#-dontwarn org.ietf.jgss.**
#
#-keepnames class com.fasterxml.jackson.** { *; }
#-dontwarn com.fasterxml.**
#
#-keepnames class javax.servlet.** { *; }
#
#-dontwarn org.w3c.dom.**
#-dontwarn org.joda.time.**
#
### Android architecture components: Lifecycle
#-keepclassmembers class android.arch.** { *; }
#-keep class android.arch.** { *; }
#-dontwarn android.arch.**
#
#
#
##Glide
#-keep public class * implements com.bumptech.glide.module.GlideModule
#-keep public class * extends com.bumptech.glide.module.AppGlideModule
#-keep public enum com.bumptech.glide.load.ImageHeaderParser$** {
#  **[] $VALUES;
#  public *;
#}
#-dontwarn com.bumptech.glide.load.engine.bitmap_recycle.LruBitmapPool
#-dontwarn com.bumptech.glide.load.resource.bitmap.Downsampler
#-dontwarn com.bumptech.glide.load.resource.bitmap.HardwareConfigState
#
#-keep class com.google.**
#-dontwarn com.google.**
#
#-keep class org.ocpsoft.prettytime.** {*;}
#-dontwarn org.ocpsoft.prettytime.**
#-keepnames class ** implements org.ocpsoft.prettytime.TimeUnit
#
#
##ViewModel
#
### Android architecture components: Lifecycle
## LifecycleObserver's empty constructor is considered to be unused by proguard
#-keep class androidx.lifecycle.** { *; }
#
#
##all
#
#-ignorewarnings
#-keep class * {
#    public private *;
#}
#
#-keep class com.google.android.gms.** { *; }
#-dontwarn com.google.android.gms.**
#
#-dontwarn org.xmlpull.v1.**
#-dontnote org.xmlpull.v1.**
#-keep class org.xmlpull.** { *; }
#
#
#-dontwarn okio.**
#-dontwarn com.squareup.okhttp.**
#-dontwarn okhttp3.**
#-dontwarn javax.annotation.**
#-dontwarn com.android.volley.toolbox.**
#
## com.github.siyamed:android-shape-imageview
#-dontwarn android.support.v7.**
#-keepattributes *Annotation,Signature
#-dontwarn com.github.siyamed.**
#-keep class com.github.siyamed.shapeimageview.**{ *; }
#-dontwarn org.xmlpull.v1.**
#-dontwarn uk.co.senab.photoview.**
#
##Image Cropper
#-keep class androidx.appcompat.widget.** { *; }
#
#
#
## Keep source file names, line numbers, and Parse class/method names for easier debugging
# -keepattributes SourceFile,LineNumberTable
# -keepnames class com.parse.** { *; }
#
#
# # Required for Parse
# -keepattributes *Annotation*
# -keepattributes Signature
# -dontwarn com.squareup.**
# -dontwarn okio.**
#
#
#-keepattributes SourceFile,LineNumberTable
#-keep class com.parse.*{ *; }
#-dontwarn com.parse.**
#-dontwarn com.squareup.picasso.**
#-keepclasseswithmembernames class * {
#    native <methods>;
#}
#
#
#-keep class javax.inject.** { *; }
#-keep class **$$ModuleAdapter
#-keep class **$$InjectAdapter
#-keep class **$$StaticInjection
#
-keep class dagger.** { *; }
-keep class * extends dagger.** { *; }
-keep interface dagger.** {*;}
-dontwarn dagger.internal.codegen.**

-keep class * extends dagger.hilt.*
#
#
#-keep class android.support.v4.app.CoreComponentFactory.**{*;}
#-keep class com.test.dummyappv3.utils.WrapContentLinearLayoutManager.** { *; }
#
#
##crashlytics
-keepattributes *Annotation*
-keepattributes SourceFile,LineNumberTable
-keep public class * extends java.lang.Exception
#-printmapping mapping.txt

-keep class com.crashlytics.** { *; }
-dontwarn com.crashlytics.**

-keep class com.blogspot.abtallaldigital.bloggy.models.* {*;}

解决方案

核心原因

Retrofit通过反射解析接口方法的泛型返回类型(如Call<PostList>)生成服务代理,ProGuard默认会移除泛型签名信息或混淆接口方法的类型元数据,导致HttpServiceMethod.parseAnnotations无法将类型转换为ParameterizedType,从而抛出异常。

修正后的ProGuard规则

在现有配置中添加以下规则:

# 保留Retrofit核心类与接口
-keep class retrofit2.** { *; }
-keep interface retrofit2.** { *; }
-dontwarn retrofit2.**

# 保留泛型签名、内部类等关键元数据
-keepattributes Signature, InnerClasses, EnclosingMethod

# 保留你的Retrofit API接口(替换为实际接口所在包路径)
-keep interface com.blogspot.abtallaldigital.bloggy.data.api.** { *; }

# 保留Retrofit注解的方法及其泛型信息
-keepclassmembers,allowshrinking,allowobfuscation interface * {
    @retrofit2.http.* <methods>;
}

说明

  1. 确保com.blogspot.abtallaldigital.bloggy.data.api.**替换为你实际存放Retrofit接口的包路径;
  2. 已有的-keep class com.blogspot.abtallaldigital.bloggy.models.* {*;}规则无需修改,它能保证数据模型类不被混淆,避免解析响应时出错;
  3. 添加后重新构建混淆包,提交到Google Play预启动测试验证问题是否解决。

内容的提问来源于stack exchange,提问作者Dr Mido

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 08:49:50