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>; }
说明
- 确保
com.blogspot.abtallaldigital.bloggy.data.api.**替换为你实际存放Retrofit接口的包路径; - 已有的
-keep class com.blogspot.abtallaldigital.bloggy.models.* {*;}规则无需修改,它能保证数据模型类不被混淆,避免解析响应时出错; - 添加后重新构建混淆包,提交到Google Play预启动测试验证问题是否解决。
内容的提问来源于stack exchange,提问作者Dr Mido
相关产品推荐
相关产品推荐

