Resolving R8 Errors in AGP 8.0
Summary: add the R8 rule
I updated Android Studio and thought everything was fine, but then it crashed.
Caused by: java.lang.IllegalArgumentException: Call return type must be parameterized as Call<Foo> or Call<? extends Foo>
at retrofit2.DefaultCallAdapterFactory.get(SourceFile:42)
at retrofit2.Retrofit.nextCallAdapter(SourceFile:253)
at retrofit2.Retrofit.callAdapter(SourceFile:237)
at retrofit2.HttpServiceMethod.createCallAdapter(SourceFile:114)
With some exceptions, I can get a pretty good idea of what’s going on just by looking at them, but this one is so unfamiliar and awkward that I can’t quite put my finger on it. However, it happened during execution, and it happened in a binary that was fine up until that point, and then R8 was applied, so R8 is the prime suspect.
But I didn’t touch Retrofit this time, so why did it suddenly happen? I do some searching, but I don’t have an exact solution. I found a question with the same error message, but it’s not the answer I’m looking for. I decided to dig a little deeper.
I went into Retrofit repository and saw that there hasn’t been a release since May 20th, which means I don’t need to update something, so I went to the Issues page and saw this.
At first I thought this was completely unrelated, but then I scrolled down a bit further and it said to apply the R8 rules from here. I haven’t even updated Retrofit, so why do I have to do this all of a sudden?
I can’t understand, but it said to try it, so I added this file,
It doesn’t give me an error 😱
Before I even have a moment to wonder what the heck is going on, I get another exception. This time, GSON is the problem.
java.lang.IllegalStateException: TypeToken must be created with a type argument: new TypeToken<…>() {}; When using code shrinkers (ProGuard, R8, …) make sure that generic signatures are preserved.
at com.google.gson.reflect.TypeToken.getTypeTokenTypeArgument(SourceFile:100)
at com.google.gson.reflect.TypeToken.<init>(SourceFile:70)
The exception message is kind enough to tell me to check R8. So let’s go straight to GSON repository this time. There’s something on the Troubleshooting page, and it isolated the rule as shown below.
I didn’t have gson in my R8 rules before, but they added something this time. Anyway, when I add this, the problem went away and it ran fine.
Why?
I suspected R8 from the beginning, but I wondered why the problem was happening when I hadn’t updated anything, whether Retrofit or gson. It was after updating Android Studio and AGP, so I went over there and found this: https://developer.android.com/build/releases/gradle-plugin#default-changes
There is a behavior change from AGP 8.0, and the description of android.enableR8.fullMode is as follows:
AGP 8.0 enables R8 full mode by default. for more details, see R8 full mode.
Full mode… something smells. let’s dive into it
R8 was running in compatibility mode with ProGuard. I think I read about that when R8 first came out, but I forgot it. As of AGP 8.0, it’s not compatibility mode by default, it’s full mode, and it’s optimizing more aggressively. So suddenly you have to write more detailed R8 rules.
I already found the rule above and solved all the problems, but when I looked at the R8 FAQ document, it summarized the problems with Retrofits and gson. I feel like I lost something 😭
Thanks for reading