Not a direct subclass of GenericTypeIndicator: class com.google.firebase.database.GenericTypeIndicator
Asked Answered
D

6

7

I have Firebase App with the Realtime Database, I have db.json as:

{
  "brs" : {
    "route": [
      {
        "routeDestination": "DDDD1",
        "routeOrigin": "OOOO1",
        "bus" : {
            "busArrivalTime" : "created_at_timestamp",
            "busDepartureTime" : "created_at_timestamp",
            "busName" : "SOME NAME",
            "busSeatCost" : "0000",
            "busTotalSeats" : "000",
            "reservations": [
              {
                "reservationId": 1,
                "reservationDate": "Wed Jul 06 23:54:56 EDT 2016",
                "seats": [
                  {                
                    "seatNumber": 1
                  },
                  {               
                    "seatNumber": 2
                  }
                ]
              }
            ] 
        }            
      },
      {
        "routeDestination": "DDDD2",
        "routeOrigin": "OOOO2",
        "bus" : {
            "busArrivalTime" : "created_at_timestamp",
            "busDepartureTime" : "created_at_timestamp",
            "busName" : "SOME NAME",
            "busSeatCost" : "0000",
            "busTotalSeats" : "000",
            "reservations": [
              {
                "reservationId": 1,
                "reservationDate": "Wed Jul 06 23:54:56 EDT 2016",
                "seats": [
                  {                
                    "seatNumber": 1
                  },
                  {               
                    "seatNumber": 2
                  }
                ]
              }
            ] 
        }            
      },
      {
        "routeDestination": "DDDD3",
        "routeOrigin": "OOOO3",
        "bus" : {
            "busArrivalTime" : "created_at_timestamp",
            "busDepartureTime" : "created_at_timestamp",
            "busName" : "SOME NAME",
            "busSeatCost" : "0000",
            "busTotalSeats" : "000",
            "reservations": [
              {
                "reservationId": 1,
                "reservationDate": "Wed Jul 06 23:54:56 EDT 2016",
                "seats": [
                  {                
                    "seatNumber": 1
                  },
                  {               
                    "seatNumber": 2
                  }
                ]
              }
            ] 
        }            
      }
    ]
  }
}

Now in android App I want to retrieve the routes in a list as

button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(final View view) {
        FirebaseDatabase firebaseDatabase = FirebaseDatabase.getInstance();
        DatabaseReference myRef = firebaseDatabase.getReference("route");

        try {
          
            // Read from the database
            myRef.addValueEventListener(new ValueEventListener() {
                @Override
                public void onDataChange(DataSnapshot dataSnapshot) {
                    // This method is called once with the initial value and again
                    // whenever data at this location is updated.
                    GenericTypeIndicator t = new GenericTypeIndicator () {};
                    List<Object> routes = (List<Object>) dataSnapshot.getValue(t);
                    
                    if( routes == null ) {
                        Snackbar.make(view, "No value  " ,Snackbar.LENGTH_LONG).setAction("Action", null).show();
                    }
                    else {
                        Snackbar.make(view, "The routes Size is " + routes.size(), Snackbar.LENGTH_LONG)
                                .setAction("Action", null).show();
                       
                    }                        
                }

                @Override
                public void onCancelled(DatabaseError error) {
                    // Failed to read value
                    Log.w("BUS_TAG", "Failed to read value.", error.toException());
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }    

    }
});

through this code I'm getting

E/AndroidRuntime: FATAL EXCEPTION: main
     Process: com.rhcloud.escot.bsr, PID: 1750
     com.google.firebase.database.DatabaseException: Not a direct subclass of GenericTypeIndicator: class com.google.firebase.database.GenericTypeIndicator
         at com.google.android.gms.internal.zzalq.zza(Unknown Source)
         at com.google.firebase.database.DataSnapshot.getValue(Unknown Source)
         at com.rhcloud.escot.bsr.MainActivity$2$1.onDataChange(MainActivity.java:61)
         at com.google.android.gms.internal.zzaih.zza(Unknown Source)
         at com.google.android.gms.internal.zzajh.zzctc(Unknown Source)
         at com.google.android.gms.internal.zzajk$1.run(Unknown Source)
         at android.os.Handler.handleCallback(Handler.java:815)
         at android.os.Handler.dispatchMessage(Handler.java:104)
         at android.os.Looper.loop(Looper.java:194)
         at android.app.ActivityThread.main(ActivityThread.java:5631)
         at java.lang.reflect.Method.invoke(Native Method)
         at java.lang.reflect.Method.invoke(Method.java:372)
         at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:959)
         at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:754)
07-20 09:07:05.756 757-1407/? W/ActivityManager:   Force finishing activity 1 com.rhcloud.escot.bsr/.MainActivity

Are there any parts that I'm missing here to read the routes list.

Davina answered 20/7, 2016 at 4:22 Comment(2)
Which version of google play services are you using ?Malang
Not any! Is it necessary to add that compile 'com.google.android.gms:play-services:9.2.1' Davina
L
14

I had this same issue today and got fixed by adding this line to ProGuard / R8 config:

-keepclassmembers class com.google.firebase.database.GenericTypeIndicator { *; }
Limitation answered 1/3, 2022 at 8:58 Comment(4)
This is crazy - today after updating build tools to 7.1.2 (up from 7.0.4) - the release build was having a strange behaviour and it turned out we needed to add this to the proguard file... In all my time as a developer this takes the price for the most insane thing I've seen - and I've seen a lot...Reareace
That's why we have SO.. to save each other from insanity!Limitation
Please accept this answer! I wasted 2 days before apply this rule... (make sure to add it to app module)Rutharuthann
In my case in addition to the line mentioned in the answer I had to add this line as well: -keep class * extends com.google.firebase.database.GenericTypeIndicator { *; } This was needed in my case because my project had a custom transformer (MapTransformer) and it was implementing that object : GenericTypeIndicator in app code. So, adding that "extends" to proguard rules helped meTver
S
6

instead of this:

 GenericTypeIndicator t = new GenericTypeIndicator () {};
 List<Object> routes = (List<Object>) dataSnapshot.getValue(t);

use this

GenericTypeIndicator<List<Object>> t = new GenericTypeIndicator <List<Object>>() {};
List<Object> routes = dataSnapshot.getValue(t);
Surat answered 9/1, 2017 at 14:26 Comment(0)
E
2

Unfortunately, none of the following lines of code worked for me:

-keepclassmembers class com.google.firebase.database.GenericTypeIndicator { *; }
-keep class * extends com.google.firebase.database.GenericTypeIndicator { *; }

The problem was because of the way I read the data from the Realtime Database:

suspend fun getData() = try {
    val data = db.reference.child("data").get().await().getValue<Long>()
    //                                                            👆
    Result.Success(data)
} catch (e: Exception) {
    Result.Failure(e)
}

When I change the above line with:

val data = db.reference.child("data").get().await().getValue(Long::class.java)
//                                                            👆

Everything worked fine. So it's best to convert the data into an object of the specific class passing the class as an argument to the getValue() method.

Eda answered 5/3, 2024 at 15:38 Comment(9)
How do I do this when have multiple layers of generics like val value = db.getValue<List<Long>>()?Davidadavidde
whats correct? I have posted the old, non-functional, way and I am wondering how to adapt it for your, working, way.Davidadavidde
@Davidadavidde Oh, yes. Ups. You can use val value = db.getValue(List::class.java).Eda
Where to I tell firebase that the list is a list of longs? I am getting an exception: com.google.firebase.database.DatabaseException: Class java.util.List has generic type parameters, please use GenericTypeIndicator insteadDavidadavidde
Have you tried to define the generic type val data: List<Long>> = db.getValue(List::class.java)? Does it make any difference?Eda
That's not possible, Type mismatch. Required: List<Long>, Found: List<*>Davidadavidde
@Davidadavidde I think that in such a case, the only option that you have is to use GenericTypeIndicator.Eda
I see, I can cast to my desired type afterwards and extract that logic into a helper function. Now I have to decide if it's worth the trouble just to activate R8 full mode. Thank you very much for your help.Davidadavidde
This one saved my issue! Thank you so much!Murdocca
D
2

For me it only worked with all of these three rules:

-keepclassmembers class com.google.firebase.database.GenericTypeIndicator{*;}
-keep class * extends com.google.firebase.database.GenericTypeIndicator{*;}
-keep class com.google.firebase.database.GenericTypeIndicator{*;}
Davidadavidde answered 28/3, 2024 at 20:55 Comment(0)
I
0

The only solution that worked for me (as of October 2023) was creating a separate type indicator object and applying slightly different proguard rules.

dto:

@Keep
class MyDto {
    lateinit var id: String
    lateinit var name: String
}

type indicator object:

@Keep
object MyListTypeIndicator : GenericTypeIndicator<List<@JvmSuppressWildcards ProviderDataDto>>()

usage:

Firebase.database.getReference("YOUR_REFERENCE")
    .get()
    .await()
    .getValue(MyListTypeIndicator)

proguard rules:

-keepattributes Signature
-keep,allowobfuscation,allowshrinking class com.google.firebase.database.GenericTypeIndicator
Indusium answered 31/10, 2023 at 15:53 Comment(0)
B
0

Try adding the following rules to your proguard-rules.pro:

-keepattributes Signature
-keepclassmembers class com.your.package.firebase.entity.** {
  *;
}
-keepclassmembers class com.google.firebase.database.GenericTypeIndicator{*;}
-keep class * extends com.google.firebase.database.GenericTypeIndicator{*;}
-keep class com.google.firebase.database.GenericTypeIndicator{*;}
Birdlime answered 28/6, 2024 at 15:9 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.