Caused by java.lang.RuntimeException: Missing type parameter
Asked Answered
R

6

16

I'm retrieving a json and when I convert it to List using gson, the app crashes. The proguard is on and the problem is there.

fun getQuestions(): List<Question>? {
    val json = getQuestionsJsonData()
    return GsonBuilder().create().fromJson(
        json,
        object : TypeToken<List<Question>?>() {}.type
    )
}

As I've obfuscated my code, I'm not able to see crash log in logcat, so I send it to firebase crashlitycs. The error message is - Caused by java.lang.RuntimeException: Missing type parameter.

Maybe the Question type get's obfuscated or something similar happens. My proguard file:

-keepclassmembers,allowobfuscation class * {
  @com.google.gson.annotations.SerializedName <fields>;
}

-keepclassmembers class **.R$* {
    public static <fields>;
}

#Serialized
-keepnames class * implements java.io.Serializable
-keepclassmembers class * implements java.io.Serializable {
    static final long serialVersionUID;
    private static final java.io.ObjectStreamField[] serialPersistentFields;
    !static !transient <fields>;
    !private <fields>;
    !private <methods>;
    private void writeObject(java.io.ObjectOutputStream);
    private void readObject(java.io.ObjectInputStream);
    java.lang.Object writeReplace();
    java.lang.Object readResolve();
}

# Uncomment this to preserve the line number information for
# debugging stack traces.
-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
-renamesourcefileattribute SourceFile

Maybe I have to add something in proguard file?

P.S. The problem is only on Gradle 7.1.0

Recognition answered 3/2, 2022 at 10:36 Comment(5)
Possibly a duplicate of https://mcmap.net/q/103055/-proguard-missing-type-parameter; but it is a bit weird that this only started appearing with Gradle 7.1.0Beckford
Is this even about Gradle 7.1 or the Android Gradle plugin 7.1.0?Beckford
It's the com.android.tools.build:gradle version in application gradle file.Recognition
Gson issue #2069 describes this problem as well, but there is currently no known solution to this yet (besides your workaround mentioned below).Beckford
Thanks. BTW, I will keep this question, hence someone will find this useful.Recognition
R
17

Well, after changing my TypeToken code, seems it's working.

Non working code:

return GsonBuilder().create().fromJson(
    json,
    object : TypeToken<List<Question>?>() {}.type
)

Working solution:

return GsonBuilder().create().fromJson(
    json,
    TypeToken.getParameterized(List::class.java, Question::class.java).type
)
Recognition answered 3/2, 2022 at 11:12 Comment(0)
H
41

In my case was just adding the following to proguard configuration:

# Retain generic signatures of TypeToken and its subclasses with R8 version 3.0 and higher.
-keep,allowobfuscation,allowshrinking class com.google.gson.reflect.TypeToken
-keep,allowobfuscation,allowshrinking class * extends com.google.gson.reflect.TypeToken

Here you go the full set of options that are needed for Gson -> https://github.com/google/gson/blob/master/examples/android-proguard-example/proguard.cfg

Heliocentric answered 2/3, 2022 at 16:52 Comment(1)
Thank you.. this would help if minifyEnabled trueTrousseau
R
17

Well, after changing my TypeToken code, seems it's working.

Non working code:

return GsonBuilder().create().fromJson(
    json,
    object : TypeToken<List<Question>?>() {}.type
)

Working solution:

return GsonBuilder().create().fromJson(
    json,
    TypeToken.getParameterized(List::class.java, Question::class.java).type
)
Recognition answered 3/2, 2022 at 11:12 Comment(0)
U
6

There have been some breaking changes in the Android Gradle plugin v8.0, including the enabling of R8 full mode: https://developer.android.com/build/releases/gradle-plugin#default-changes

If none of the other options, such as keeping TypeToken classes, works for you, you can add the following command to your gradle.properties:

android.enableR8.fullMode = false

You can read more about R8 full mode here: https://r8.googlesource.com/r8/+/refs/heads/master/compatibility-faq.md#r8-full-mode

Undergraduate answered 6/7, 2023 at 22:14 Comment(0)
E
5

Add these 3 lines inside proguard-rules.pro :

-keep class com.google.gson.reflect.TypeToken
-keep class * extends com.google.gson.reflect.TypeToken
-keep public class * implements java.lang.reflect.Type
Escalera answered 26/4, 2023 at 3:2 Comment(0)
L
1

Add these lines inside proguard-rules.pro

# Retain generic signatures of TypeToken and its subclasses with R8 version 3.0 and higher.
-keep,allowobfuscation,allowshrinking class com.google.gson.reflect.TypeToken
-keep,allowobfuscation,allowshrinking class * extends com.google.gson.reflect.TypeToken
-keep class com.google.gson.reflect.TypeToken
-keep class * extends com.google.gson.reflect.TypeToken
-keep public class * implements java.lang.reflect.Type
Lionhearted answered 24/5, 2023 at 21:16 Comment(0)
A
0

In my case, I had to keep both model classes and TypeToken, if I removed anyone it won't work.

For keeping model classes

# Application classes that will be serialized/deserialized over Gson
-keep class com.example.data.models.** { *; }

For keeping TypeToken

# This is also needed for R8 in compat mode since multiple
# optimizations will remove the generic signature such as class
# merging and argument removal.
# https://r8.googlesource.com/r8/+/refs/heads/main/compatibility-faq.md#troubleshooting-gson-gson

-keep class com.google.gson.reflect.TypeToken { *; }
-keep class * extends com.google.gson.reflect.TypeToken
Aeolipile answered 28/4 at 5:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.