retrofit
retrofit copied to clipboard
R8 full mode and @Streaming giving runtime error with minifyEnabled
Using Retrofit 2.9.0 and AGP 8.0.1 with fixes from https://github.com/square/retrofit/issues/3751 I still get one more error with R8 in full mode:
E java.lang.IllegalArgumentException: Response must include generic type (e.g., Response<String>)
for method ContentApi.getRawFile
at retrofit2.Utils.methodError(SourceFile:54)
at retrofit2.Utils.methodError(SourceFile:43)
at retrofit2.HttpServiceMethod.parseAnnotations(SourceFile:77)
at retrofit2.ServiceMethod.parseAnnotations(SourceFile:39)
at retrofit2.Retrofit.loadServiceMethod(SourceFile:202)
at retrofit2.Retrofit$1.invoke(SourceFile:160)
at java.lang.reflect.Proxy.invoke(Proxy.java:1006)
at $Proxy23.getRawFile(Unknown Source)
at com.kivra.android.repository.ContentFileDownloader.downloadFile(SourceFile:40)
at com.kivra.android.repository.ContentPartFileTransform.fetchContentFiles(SourceFile:56)
at com.kivra.android.repository.ContentPartFileTransform.access$fetchContentFiles(SourceFile:28)
at com.kivra.android.repository.ContentPartFileTransform$transformData$2.invokeSuspend(SourceFile:42)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(SourceFile:33)
at kotlinx.coroutines.DispatchedTask.run(SourceFile:106)
at kotlinx.coroutines.internal.LimitedDispatcher.run(SourceFile:42)
at kotlinx.coroutines.scheduling.TaskImpl.run(SourceFile:95)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(SourceFile:570)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(SourceFile:750)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(SourceFile:677)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(SourceFile:664)
This is how the signature looks like:
@Streaming
@GET("{apiVersion}/{actorType}/{actorKey}/content/{contentKey}/file/{fileKey}/raw/{fileName}")
suspend fun getRawFile(
@Path("apiVersion") apiVersion: String,
@Path("actorType") actorType: String,
@Path("actorKey") actorKey: String,
@Path("contentKey") contentKey: String,
@Path("fileKey") fileKey: String,
@Path("fileName") fileName: String
): Response<ResponseBody>
My best guess is that <ResponseBody> is getting stripped away but I don't know how to configure to not remove it. I thought this would have done it but apparently not:
# R8 full mode strips generic signatures from return types if not kept.
-if interface * { @retrofit2.http.* public *** *(...); }
-keep,allowoptimization,allowshrinking,allowobfuscation class <3>
So perhaps something is missing still from this commit: https://github.com/square/retrofit/commit/59d302aedce5edae4806efac57b630d4fe8c27db ?
That commit is not in the released version. Copy it into your project shrinker config and it should work until the next version is released.
Ah sorry! I was meaning to say I added that bit locally and it did not fix this issue
Keeping the replaced rules and adding the new ones from the commit https://github.com/square/retrofit/commit/59d302aedce5edae4806efac57b630d4fe8c27db fixed the issue for me.
# 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
-keep,allowobfuscation,allowshrinking interface retrofit2.Call
-keep,allowobfuscation,allowshrinking class retrofit2.Response
# R8 full mode strips generic signatures from return types if not kept.
-if interface * { @retrofit2.http.* public *** *(...); }
-keep,allowoptimization,allowshrinking,allowobfuscation class <3>
I have same problem when update AndroidStudio Flamingo & Gradle8.0.2
When i call a post method, crash:
java.lang.IllegalArgumentException: Unable to create call adapter for interface w4.d
But i solve this, add "retrofit/src/main/resources/META-INF/proguard/retrofit2.pro" all code into my proguard-rules.pro file
Maybe we can wait for retrofit2 update new version to solve this problem totally.
I am facing a similar issue with @Streaming
annotated functions, not really a crash but just the app loading forever (only on minified builds).
What is interesting to point out is:
- This works on debug builds (
minifyEnbaled = false
) - This does not works on signed builds (
minifyEnbaled = true
). Note: Tried both fullR8Support enabled and disabled. - This works on signed builds (
minifyEnbaled = true
) if I add theHttpLoggingInterceptor
Finally, I have 2 very similar interfaces that are @Streaming
annotated, and one works while the other doesn't (on signed builds with minifyEnbaled = true
).
The working one is something like
@Streaming
@GET
suspend fun downloadFile(@Url fileUrl: String): ResponseBody
The non-working one is something like:
@Streaming
@GET("api/{${MY_ID}}/bob")
suspend fun downloadDocument(@Path(MY_ID) myId: String, @Query(TYPE) type: String): ResponseBody
The only difference I can spot between the two is the different types of params added?
Update: removing the @Streaming
tag solves the issue 🤔 Although that could be explained by the network protocol not supporting it, it still doesn't explain why it works on debug builds or with the logging interceptor 😅