9

I'm new to Firebase, and I've been really enjoying it so far. I'm running into a problem; I'm using the FirebaseListAdapter similar to the tutorial outline here: https://github.com/firebase/AndroidChat

To use the FirebaseListAdapter, I need to use data model objects (to get the automatic binding to work nicely). The problem is I also want to keep a timestamp value with that model object, and I want to get the timestamp from the Firebase server.

What I have currently that is NOT working is a class DataModelObject (similar to com.firebase.androidchat.Chat in the demo example) with a constructor like :

DataModelObject(String data1, String data2, Map enQTimeStamp)

which I then try to use like this:

DataModelObject dmo = new DataModelObject ("foo", "bar", ServerValue.TIMESTAMP);
myFirebaseRef.push().setValue(dmo);

This causes a JsonMappingException when I try to run that code. I found a code snippet here :

https://www.firebase.com/blog/2015-02-11-firebase-unique-identifiers.html

But it's worthwhile to note that on line 4 of the Android code example, that will cause a compile time error (as he is trying to put ServerValue.TIMESTAMP into a Map, and TIMESTAMP is a Map itself)

What is the right way to do this and maintain compatibility with FirebaseListAdapter?

mkim
  • 113
  • 1
  • 1
  • 8
  • http://stackoverflow.com/questions/25500138/android-chat-crashes-on-datasnapshot-getvalue-for-timestamp/25512747#25512747 – vishwajit76 Dec 18 '16 at 12:30

6 Answers6

21

This sounds similar to this question: When making a POJO in Firebase, can you use ServerValue.TIMESTAMP?

When creating POJOs used to store/retrieve data apart from the default empty constructor I usually use a constructor similar to this:

Param param1;
Param param2;
HashMap<String, Object> timestampCreated;

//required empty constructor
public DataObject(){}

public DataObject(Param param1, Param param2) {
       this.param1 = param1;
       this.param2 = param2;
       HashMap<String, Object> timestampNow = new HashMap<>();
       timestampNow.put("timestamp", ServerValue.TIMESTAMP);
       this.timestampCreated = timestampNow;
}

Be sure to include a getter for the HashMap<> used to store the Timestamp:

public HashMap<String, Object> getTimestampCreated(){
    return timestampCreated;
}

Then use the @Exclude annotation to create a getter that you can use in your code to get the value of the timestamp if you need it. The @Exclude annotation will cause Firebase to ignore this getter and not look for a corresponding property

@Exclude
public long getTimestampCreatedLong(){
    return (long)timestampCreated.get("timestamp");
}
Community
  • 1
  • 1
Kevin O'Neil
  • 1,411
  • 1
  • 15
  • 15
  • I've recently started with Firebase as well. First if you haven't already check out the Firebase course for Android on Udacity, I found it EXTREMELY helpful. If I'm reading your question right the course covers this exact issue. – Kevin O'Neil Apr 16 '16 at 02:49
  • Thanks for the info. I went through the examples on Firebase's website, but I must have missed the link out to the Udacity course. I'll check it out. – mkim Apr 18 '16 at 17:37
  • what is the correlation between the timestampNow and timestampCreated? , i see no connection there, how can this worked ? – Goofy_Phie Apr 27 '17 at 04:10
  • this way, would make timestamp nested inside timestampcreated in db, e.g : timestampcreated : ----timestamp : 14400202232xx, while i need timestamp:144002921100xx – Goofy_Phie Apr 27 '17 at 12:26
  • in response to your first comment there was an error in the code...I forgot to assign the local variable timestampNow to the class variable timestampCreated...I have corrected it, thanks for pointing it out. – Kevin O'Neil Apr 27 '17 at 15:56
  • The ServerValue.TIMESTAMP is a Map so the method I'm using makes it easier to create and retrieve the value from your database – Kevin O'Neil Apr 27 '17 at 16:08
  • When i get the method to get the timestamp in Long i will get the exception: Caused by: java.lang.ClassCastException: java.util.Collections$UnmodifiableMap cannot be cast to java.lang.Long – Taras Vovkovych Aug 06 '20 at 22:26
13

Here's how I do it

//member variable
Object createdTimestamp;

public YourConstructor(){
    createdTimestamp = ServerValue.TIMESTAMP
}

@Exclude
public long getCreatedTimestampLong(){
    return (long)createdTimestamp;
}
MobileMon
  • 8,341
  • 5
  • 56
  • 75
3

Your db object should include these:

public class FirebaseDbObject {

    private final Object timestamp = ServerValue.TIMESTAMP;

    //........
    //........

    Object getTimestamp() {
        return timestamp;
    }

    @Exclude
    public long timestamp() {
        return (long) timestamp;
    }

}

This will add an extra field called "timestamp" to your object.

Edit: The answer posted by MobileMon is not fully correct as it does not have getter method. This is the complete and correct answer.

Ugurcan Yildirim
  • 5,973
  • 3
  • 42
  • 73
0

Kotlin provides an easy way to achieve this by data classes. You can create it like

data class FirebaseRequestModel(
        var start_time: Any = ServerValue.TIMESTAMP,
        var stop_time: Long = 0,
        var total_time: Long = 0,
)

and use it directly by

val firebaseModel = FirebaseRequestModel()
firebaseRef.setValue(firebaseModel)

This will get default values from data class.

Or even you can initiate your own values by

val firebaseModel = FirebaseRequestModel(ServerValue.TIMESTAMP, 2134, 0)
firebaseRef.setValue(firebaseModel)
Kishan Solanki
  • 13,761
  • 4
  • 85
  • 82
  • Don't know if your code helps the OP but its half of the kotlin code I was looking for. Thanks – Eaweb Aug 12 '19 at 12:10
0

Similar to Urgurcan's answer, but a bit cleaner so the caller doesn't have trouble guessing between getTimestamp vs timestamp.

public class FirebaseDbObject {

    private Object timestamp = ServerValue.TIMESTAMP;

    //........
    //........
    @PropertyName("timestamp")
    Object getRawTimestamp() {
        return timestamp;
    }

    @Exclude
    public long getTimestamp() {
        return (long) timestamp;
    }

}
-1

You can do it:

public class MyTimeStamp {
    private Object timestamp;

    public MyTimeStamp() {

    }

    public Object getTimestamp() {
        return timestamp;
    }

    public void setTimestamp(Object timestamp) {
        this.timestamp = timestamp;
    }
}

And so:

public static void start(Context context) {
    MyTimeStamp timeStamp = new MyTimeStamp();
    timeStamp.setTimestamp(ServerValue.TIMESTAMP);

    Log.d(TAG, "start: ", timeStamp.getTimestamp().toString());
}