Retrieve ServerValue.Timestamp from Firebase in Android app, when data is sent
Asked Answered
P

4

7

I would like to know how to use Firebase's ServerValue.TIMESTAMP method, when I want to create a timestamp at the Firebase server, and then retrieve it to the local client.

In Firebase guides, only javascript has a more detailed description of this case, but I'm having a hard time figureing how to translate this in to my Android appliction.

Thanks in advance!

Protectionist answered 9/9, 2014 at 12:16 Comment(3)
See https://mcmap.net/q/1477008/-what-does-com-firebase-client-servervalue-timestamp-respong-withTracy
Thanks, but I wanted to know the syntax in Java, not javascript, as in the answer there. Anyone able to translate that js snippet? :)Protectionist
It was a Java/Android question, but indeed that answer is JavaScript based. The OP found a solution and posted that, but since deleted it. Maybe you can still access it at https://mcmap.net/q/1477008/-what-does-com-firebase-client-servervalue-timestamp-respong-withTracy
S
11

Firebase.ServerValue.TIMESTAMP is set as a Map (containing {.sv: "timestamp"}) which tells Firebase to populate that field with the server's time. When that data is read back, it is the actual unix time stamp which is a Long.

Something like this will work:

Firebase ref = new Firebase("https://YOUR-FIREBASE.firebaseio.com");    

ref.addValueEventListener(new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot snapshot) {
        Long timestamp = (Long) snapshot.getValue();
        System.out.println(timestamp);
    }

    @Override
    public void onCancelled(DatabaseError databaseError) {

    }
});

ref.setValue(ServerValue.TIMESTAMP);

For another example, you can see my answer to this question: Android chat crashes on DataSnapshot.getValue() for timestamp

Sven answered 9/9, 2014 at 17:38 Comment(1)
How to can we know the value when we do updateChildren?Roede
B
2

I know this question already been answered, but I wanted to share my version of the solution.

When I use the server's timestamp, i usually need to use it more than once, i.e I have some kind of startTime and endTime which both depend on the server's time, where startTime is NOW and endTime is X seconds / minutes / hours after startTime, so to spare the multiple requests to the server I save the server's time in a root child called serverTime in the database, and I use it to set all dependent values.

Another thing, because of the way Firebase works with the ServerValue.Timestamp, eventually it fires 2 events (added and changed), the first one with local timestamp and the second with the actual server's timestamp. So to overcome the issue of not receiving the correct time I added a simple OnCompleteListener.

A short example code:

import android.support.annotation.NonNull;

import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.ServerValue;
import com.google.firebase.database.ValueEventListener;

public class ServerTime {

    public interface OnTimeRetrievedListener {

        void onTimeRetrieved(Long timestamp);
    }

    private final DatabaseReference db;

    public ServerTime(DatabaseReference db) {
        this.db = db.child("serverTime");
    }

    /**
     * Gets the server's timestamp in milliseconds.
     * @param listener {@link OnTimeRetrievedListener}
     */
    public void getTime(final OnTimeRetrievedListener listener) {
        if (listener == null) {
            return;
        }

        db.setValue(ServerValue.TIMESTAMP).addOnCompleteListener(new OnCompleteListener<Void>() {
            @Override
            public void onComplete(@NonNull Task<Void> task) {

                db.addListenerForSingleValueEvent(new ValueEventListener() {
                    @Override
                    public void onDataChange(DataSnapshot dataSnapshot) {
                        listener.onTimeRetrieved(dataSnapshot.getValue(Long.class));
                    }

                    @Override
                    public void onCancelled(DatabaseError databaseError) { }
                });

            }
        });
    }
}
Bein answered 13/1, 2017 at 22:47 Comment(0)
L
2

If you don't want to write to database to figure out the timestamp, you can get instant approximation of it. Works even offline and it's good enough for most cases.

Read value

/.info/serverTimeOffset

And add it to new Date().time()

Liana answered 13/4, 2017 at 21:34 Comment(1)
Seems to be a good answer, can you please extend your answer for total newbies. ThanksPellikka
L
2

First, send an object to the firebase server

FirebaseDatabase.getInstance().getReference("serverTimeTest").setValue(new KKModel());

Model class

class KKModel{
    public String someField = "value";
    public Object creationDate = ServerValue.TIMESTAMP;

    public String creationDate() {
        return SimpleDateFormat.getDateInstance(DateFormat.SHORT, Locale.US).format(creationDate);
    }
}

Usage

object.creationDate() working fine test results "9/6/18"

Lanchow answered 6/9, 2018 at 12:8 Comment(3)
It is not working. The object cannot be converted to DateFormat.Endoblast
@Endoblast once you push that object to firebase then it worksLanchow
Sorry, but its not working. It will throw exception.Endoblast

© 2022 - 2024 — McMap. All rights reserved.