Search code examples
javaandroidfirebasegoogle-cloud-firestorefirebaseui

Error in getting server timestamp in Firestore


I'm trying to add a document in Cloud Firestore, but I need the server timestamp for adding the document. Documents are successfully added in the collection with the correct timestamp. I'm adding the document with an alert dialog. But when I'm returning to my activity app terminates with following errors:

java.lang.RuntimeException: java.lang.reflect.InvocationTargetException ........ E/AndroidRuntime: Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.util.Date com.google.firebase.Timestamp.toDate()' on a null object reference at com.sasam.virtuallibrary.Models.UserLight.setTimestamp(UserLight.java:103)

For showing document's I'm using following query

Query query= FirebaseFirestore.getInstance()
                .collection("Users")
                .document(user.getUid())
                .collection("friends")
                .orderBy("timestamp", Query.Direction.DESCENDING);

My class is here

public class UserLight{

    protected String name;
    protected String email;
    protected String uid;
    protected Float rating;
    protected String photoUrl;
    protected long timestamp;


    public UserLight(){

    }

    //other getters and setters

    @Exclude
    public long getTimestampLong(){
        return timestamp;
    }
    public FieldValue getTimestamp() {
        return  FieldValue.serverTimestamp();
    }

    public void setTimestamp(Timestamp timestamp) {
        this.timestamp = timestamp.toDate().getTime();
    }

}

Code that deals with the snapshot from the query

Query query= FirebaseFirestore.getInstance()
                .collection("Users")
                .document(user.getUid())
                .collection("friends")
                .orderBy("timestamp", Query.Direction.DESCENDING);

        PagedList.Config config = new PagedList.Config.Builder()
                .setEnablePlaceholders(false)
                .setPrefetchDistance(5)
                .setPageSize(10)
                .build();

        FirestorePagingOptions<UserLight> options = new FirestorePagingOptions.Builder<UserLight>()
                .setLifecycleOwner(this)
                .setQuery(query, config, UserLight.class)
                .build();


        mAdapter = new FirestorePagingAdapter<UserLight, ItemFriendViewHolder>(options) {
            @NonNull
            @Override
            public ItemFriendViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
                return new ItemFriendViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.rc_item_friend, parent, false));
            }

            @Override
            protected void onBindViewHolder(@NonNull ItemFriendViewHolder holder, int position, @NonNull final UserLight userLight) {


                holder.txtName.setText(userLight.getName());
                GlideApp.with(holder.context).load(userLight.getPhotoUrl()).into(holder.avata);

                holder.cardView.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        Intent intent=new Intent(FriendListActivity.this,FinalChatActivity.class);
                        intent.putExtra("Friend", (Serializable) userLight);
                        startActivity(intent);
                    }
                });

            }

            @Override
            protected void onLoadingStateChanged(@NonNull LoadingState state) {
                switch (state) {
                    case LOADING_INITIAL:
                    case LOADING_MORE:
                        // Do your loading animation
                        mSwipeRefreshLayout.setRefreshing(true);
                        break;

                    case LOADED:
                        // Stop Animation
                        mSwipeRefreshLayout.setRefreshing(false);
                        break;

                    case FINISHED:
                        //Reached end of Data set
                        mSwipeRefreshLayout.setRefreshing(false);
                        break;

                    case ERROR:
                        retry();
                        break;
                }
            }


            @Override
            protected void onError(@NonNull Exception e) {
                super.onError(e);
                mSwipeRefreshLayout.setRefreshing(false);
            }

        };

        recyclerView.setAdapter(mAdapter);

        mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                mAdapter.refresh();
            }
        });

Document's after insertion enter image description here


Solution

  • The problem in your code is the fact that the type of your timestamp field inside your UserLight class dosn't match the type of your timestamp property in the database. See, in your UserLight class the timestamp field is of type long, which is basically a number while in the database is of type Date or Timestamp. Please note that both must match.

    Because the correct way of holding dates in Cloud Firestore is to use the Date or Timestamp class, to solve this, simply change type of your timestamp field in your model class to be Date, as explained in my answer from the following post: