1

This line:

ProjectMap m = document.toObject(ProjectMap.class);

Generates the error:

E/AndroidRuntime: FATAL EXCEPTION: main Process: com.dockdogs.lorecoords, PID: 5633 java.lang.RuntimeException: Could not deserialize object. Class com.dockdogs.lorecoords.preferences.MapPreference$Bubble does not define a no-argument constructor. If you are using ProGuard, make sure these constructors are not stripped (found in field 'preferences.mapBubble') at com.google.firebase.firestore.util.CustomClassMapper.deserializeError(CustomClassMapper.java:563) at com.google.firebase.firestore.util.CustomClassMapper.access$200(CustomClassMapper.java:54) at com.google.firebase.firestore.util.CustomClassMapper$BeanMapper.deserialize(CustomClassMapper.java:749) at com.google.firebase.firestore.util.CustomClassMapper$BeanMapper.deserialize(CustomClassMapper.java:741) at com.google.firebase.firestore.util.CustomClassMapper.convertBean(CustomClassMapper.java:542) at com.google.firebase.firestore.util.CustomClassMapper.deserializeToClass(CustomClassMapper.java:253) at com.google.firebase.firestore.util.CustomClassMapper.deserializeToType(CustomClassMapper.java:189) at com.google.firebase.firestore.util.CustomClassMapper.access$300(CustomClassMapper.java:54) at com.google.firebase.firestore.util.CustomClassMapper$BeanMapper.deserialize(CustomClassMapper.java:778) at com.google.firebase.firestore.util.CustomClassMapper$BeanMapper.deserialize(CustomClassMapper.java:741) at com.google.firebase.firestore.util.CustomClassMapper.convertBean(CustomClassMapper.java:542) at com.google.firebase.firestore.util.CustomClassMapper.deserializeToClass(CustomClassMapper.java:253) at com.google.firebase.firestore.util.CustomClassMapper.deserializeToType(CustomClassMapper.java:189) at com.google.firebase.firestore.util.CustomClassMapper.access$300(CustomClassMapper.java:54) at com.google.firebase.firestore.util.CustomClassMapper$BeanMapper.deserialize(CustomClassMapper.java:770) at com.google.firebase.firestore.util.CustomClassMapper$BeanMapper.deserialize(CustomClassMapper.java:741) at com.google.firebase.firestore.util.CustomClassMapper.convertBean(CustomClassMapper.java:542) at com.google.firebase.firestore.util.CustomClassMapper.deserializeToClass(CustomClassMapper.java:253) at com.google.firebase.firestore.util.CustomClassMapper.convertToCustomClass(CustomClassMapper.java:100) at com.google.firebase.firestore.DocumentSnapshot.toObject(DocumentSnapshot.java:183) at com.google.firebase.firestore.QueryDocumentSnapshot.toObject(QueryDocumentSnapshot.java:116) at com.google.firebase.firestore.DocumentSnapshot.toObject(DocumentSnapshot.java:161) at com.google.firebase.firestore.QueryDocumentSnapshot.toObject(QueryDocumentSnapshot.java:97) at com.dockdogs.lorecoords.SaveSystem$26.onComplete(SaveSystem.java:488) at com.google.android.gms.tasks.zzj.run(com.google.android.gms:play-services-tasks@@17.2.0:4) at android.os.Handler.handleCallback(Handler.java:938) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:246) at android.app.ActivityThread.main(ActivityThread.java:8512) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:602) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1130)

ProjectMap just looks like:

public class ProjectMap implements Serializable {
    public int height=0;
    public int width=0;
    public String id = "";
    public int scaleRatio = 1; //FOR ZOOMING THE MAP IN AND OUT
    public String mapTitle, mapPath; //map path = image path
    public boolean ISCURRENT = false; //the map that's currently being used by the user
    public ArrayList<MapEvent> mapEvents = new ArrayList<MapEvent>();
    private MapPreference preferences = new MapPreference();

}

... and MapPreferences looks like:

public class MapPreference implements Serializable {
    //Controls scale for map bitmap
    public  float minScaleX = 0.50f;
    public  float maxScaleX = 8f;
    public  float minScaleY = 0.50f;
    public  float maxScaleY = 8f;
    //end controls for scaling map bitmap


    public Dagger mapDagger = new Dagger();

    public Bubble mapBubble = new Bubble();


    public  boolean useGridLines = true;

    public  int gridCols = 0;
    public  int gridRows = 0;

    public MapPreference() {
    }


    public  void setGridRows(int gridRows) { this.gridRows = gridRows; }
    public  void setGridCols(int gridCols) { this.gridCols = gridCols; }

    //will the user have grid lines on their map?
    public  void setUseGridLines(boolean useGridLines) { this.useGridLines = useGridLines; }

    public  boolean GetUseGridLines() { return useGridLines; }

    public  int GetGridCols(){
        return gridCols;
    }
    public  int GetGridRows(){
        return gridRows;
    }

    public  float GetMinScaleX(){
        return minScaleX;
    }
    public  float GetMinScaleY(){
        return minScaleY;
    }
    public  float GetMaxScaleX(){
        return maxScaleX;
    }
    public  float GetMaxScaleY(){
        return maxScaleY;
    }
    //TODO: add a preferences page for these options
    public  void SetMinScaleX(float _minScaleX){
        minScaleX = _minScaleX;
    }
    public  void SetMinScaleY(float _minScaleY){
        minScaleY = _minScaleY;
    }
    public  void SetMaxScaleX(float _maxScaleX){
        maxScaleX = _maxScaleX;
    }
    public  void SetMaxScaleY(float _maxScaleY){
        maxScaleY = _maxScaleY;
    }


    public class Dagger implements Serializable  {
        public  float minScaleX = 0.75f;
        public  float maxScaleX = 1f;
        public  float minScaleY = 0.75f;
        public  float maxScaleY = 1f;
        public  float GetMinScaleX(){
            return minScaleX;
        }
        public  float GetMinScaleY(){
            return minScaleY;
        }
        public  float GetMaxScaleX(){
            return maxScaleX;
        }
        public  float GetMaxScaleY(){
            return maxScaleY;
        }
        //TODO: add a preferences page for these options
        public  void SetMinScaleX(float _minScaleX){
            minScaleX = _minScaleX;
        }
        public  void SetMinScaleY(float _minScaleY){
            minScaleY = _minScaleY;
        }
        public  void SetMaxScaleX(float _maxScaleX){
            maxScaleX = _maxScaleX;
        }
        public  void SetMaxScaleY(float _maxScaleY){
            maxScaleY = _maxScaleY;
        }

        public Dagger(){

        }
    }

    public class Bubble implements Serializable {
        public  float minScaleX = 0.75f;
        public  float maxScaleX = 1f;
        public  float minScaleY = 0.75f;
        public  float maxScaleY = 1f;
        public  float GetMinScaleX(){
            return minScaleX;
        }
        public  float GetMinScaleY(){
            return minScaleY;
        }
        public  float GetMaxScaleX(){
            return maxScaleX;
        }
        public  float GetMaxScaleY(){
            return maxScaleY;
        }
        //TODO: add a preferences page for these options
        public  void SetMinScaleX(float _minScaleX){
            minScaleX = _minScaleX;
        }
        public  void SetMinScaleY(float _minScaleY){
            minScaleY = _minScaleY;
        }
        public  void SetMaxScaleX(float _maxScaleX){
            maxScaleX = _maxScaleX;
        }
        public  void SetMaxScaleY(float _maxScaleY){
            maxScaleY = _maxScaleY;
        }

        public Bubble() {

        }
    }

}

I wonder if the floats are failing to retrieve properly with Firestore, but if that's true I'm not sure what I can do about it.

ALSO THIS ISN'T A DUPLICATE QUESTION BECAUSE THE CLASS ALREADY HAS AN EMPTY CONSTRUCTOR AND IT STILL THROWS THE ERROR.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
Adam R. Turner
  • 139
  • 1
  • 2
  • 14

1 Answers1

1

It seems like some of these classes are inner classes of others. In that case, you also need to mark the inner class(es) as static. Without that the default constructor will require an implicit outer parameter that Firestore can't populate for you.

So:

static public class Bubble ...

Also see (for the Realtime Database, but the logic is the same):

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807