Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

R8 full mode and @Streaming giving runtime error with minifyEnabled #3898

Open
Stofferoo opened this issue May 17, 2023 · 5 comments
Open

R8 full mode and @Streaming giving runtime error with minifyEnabled #3898

Stofferoo opened this issue May 17, 2023 · 5 comments

Comments

@Stofferoo
Copy link

Using Retrofit 2.9.0 and AGP 8.0.1 with fixes from #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 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: 59d302a ?

@JakeWharton
Copy link
Collaborator

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.

@Stofferoo
Copy link
Author

Ah sorry! I was meaning to say I added that bit locally and it did not fix this issue

@Stofferoo Stofferoo changed the title R8 full mode and @Streaming giving runtime error with miniyEnabled R8 full mode and @Streaming giving runtime error with minifyEnabled May 17, 2023
@AndroidPat
Copy link

Keeping the replaced rules and adding the new ones from the commit 59d302a 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>

@qaszxcwer
Copy link

qaszxcwer commented Jun 7, 2023

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.

@Alexs784
Copy link

Alexs784 commented Jun 21, 2023

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 the HttpLoggingInterceptor

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 😅

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants