背景
由于项目需要适配安卓14,将AGP升级到了8.2.2,并将Gradle升级到了8.2。最终代码混淆出现了很多问题,其中retrofit2的报错如下:
Caused by: java.lang.IllegalArgumentException: Unable to create call adapter for interface retrofit2.Call
for method HttpBinService.get
at retrofit2.Utils.methodError(Utils.java:55)
at retrofit2.HttpServiceMethod.createCallAdapter(HttpServiceMethod.java:116)
at retrofit2.HttpServiceMethod.parseAnnotations(HttpServiceMethod.java:67)
at retrofit2.ServiceMethod.parseAnnotations(ServiceMethod.java:39)
at retrofit2.Retrofit.loadServiceMethod(Retrofit.java:208)
at retrofit2.Retrofit$1.invoke(Retrofit.java:166)
at java.lang.reflect.Proxy.invoke(Proxy.java:1006)
at $Proxy3.get(Unknown Source)
at io.vibin.myapplication.MainActivity.onCreate(MainActivity.kt:45)
at android.app.Activity.performCreate(Activity.java:8290)
at android.app.Activity.performCreate(Activity.java:8269)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1384)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3657)
... 12 more
Caused by: java.lang.IllegalArgumentException: Call return type must be parameterized as Call<Foo> or Call<? extends Foo>
at retrofit2.DefaultCallAdapterFactory.get(DefaultCallAdapterFactory.java:42)
at retrofit2.Retrofit.nextCallAdapter(Retrofit.java:259)
at retrofit2.Retrofit.callAdapter(Retrofit.java:243)
at retrofit2.HttpServiceMethod.createCallAdapter(HttpServiceMethod.java:114)
... 23 more
经研究发现,原因是在AGP7.2以上的版本默认开启了R8完整模式。R8完整模式对未保留的类剥离通用签名。因此需要在proguard-rules.pro
中配置额外的混淆规则规避这些问题,另外也可以通过在gradle.properties
中添加android.enableR8.fullMode=false
关闭R8完整模式。
需要新增的规则
# 使用R8全模式,对未保留的类剥离通用签名。挂起函数被包装在使用类型参数的continuation中。
-keep,allowobfuscation,allowshrinking class kotlin.coroutines.Continuation
# 如果不保留,R8完整模式将从返回类型中剥离通用签名。
-if interface * { @retrofit2.http.* public *** *(...); }
-keep,allowoptimization,allowshrinking,allowobfuscation class <3>
# 在R8全模式下,对未保留的类剥离通用签名。
-keep,allowobfuscation,allowshrinking class retrofit2.Response
另外附上通用的对Retrofit2 , Rxjava2 , Okhttp3混淆规则,这里参考大佬的文章:AndroidStudio混淆打包踩坑之retrofit2.
注意,这里只是通用配置不包含R8完整模式的额外配置,请根据需求自己调整!
## ---------Retrofit混淆方法---------------
-dontwarn javax.annotation.**
-dontwarn javax.inject.**
# OkHttp3
-dontwarn okhttp3.logging.**
-keep class okhttp3.internal.**{*;}
-dontwarn okio.**
# Retrofit
-dontwarn retrofit2.**
-keep class retrofit2.** { *; }
-keepattributes Signature
-keepattributes Exceptions
# RxJava RxAndroid
-dontwarn sun.misc.**
-keepclassmembers class rx.internal.util.unsafe.*ArrayQueue*Field* {
long producerIndex;
long consumerIndex;
}
-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueProducerNodeRef {
rx.internal.util.atomic.LinkedQueueNode producerNode;
}
-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueConsumerNodeRef {
rx.internal.util.atomic.LinkedQueueNode consumerNode;
}
# Gson
-keep class com.google.gson.stream.** { *; }
-keepattributes EnclosingMethod
# Gson
-keep class com.demo.demo1.service.bean.**{*;} # 自定义数据模型的bean目录
至此问题已解决,如有其它问题欢迎大佬补充。