suggest collectionusers collectionI have a simple suggestion page where I can type title and contents, then store some other information to the Firestore, show it on ListView pages. It works fine itself, but after I send it, an error pops and it shows the bug is the timestamp toDate on the listview pages
The order of activities is listview>sending page>listview.
//the send activity
send.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
v.getId();
String title = art1.getText().toString();
String content = art2.getText().toString();
Intent intent = new Intent(create_announce_main.this, SuggestionMain.class);
// DocumentReference documentReference = firebaseFirestore.collection("announce").document("ann");
Map<String, Object> suggest = new HashMap<>();
suggest.put("title", title);
suggest.put("content", content);
suggest.put("name", name);
suggest.put("recID", recID);
suggest.put("admin_name", "");
suggest.put("response_content", "");
suggest.put("response_status", "未回覆");
suggest.put("response_time",FieldValue.serverTimestamp());
suggest.put("createdAt", FieldValue.serverTimestamp());
firebaseFirestore.collection("Suggestion").document().set(suggest).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
Toast.makeText(create_announce_main.this, "added succesfully", Toast.LENGTH_LONG).show();
}
}
});
startActivity(intent);
}
});
to listview page
//the view
DocumentReference docRef = firebaseFirestore.collection("users").document(userID);
docRef.get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
#Override
public void onComplete(#NonNull Task<DocumentSnapshot> task) {
if (task.isSuccessful()) {
DocumentSnapshot document = task.getResult();
if (document.exists()) {
Log.d("TAG", "DocumentSnapshot data: " + document.getData());
recID = document.getString("recID");
firebaseFirestore.collection("Suggestion").whereEqualTo("recID",recID).orderBy("createdAt", Query.Direction.DESCENDING).addSnapshotListener((documentSnapshots, error) -> {
ar.clear();
for (DocumentSnapshot snapshot : documentSnapshots){
idlv = snapshot.getId();
Timestamp timestamp = (Timestamp) snapshot.getData().get("createdAt");
**Date date = timestamp.toDate();//the error is at here**
String date2 = date.toString();
ar.add(new itemAnnounce(R.drawable.notes, snapshot.getString("title"),"回饋於 "+date2,"回覆管理者:"+snapshot.getString("admin_name"),"回覆狀態:"+snapshot.getString("response_status"),idlv,url));
}
adapterAnnounce adapterAnnounce = new adapterAnnounce(getApplicationContext(), R.layout.list_row_announce, ar);
adapterAnnounce.notifyDataSetChanged();
lv1.setAdapter(adapterAnnounce);
lv1.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Object selectedObj =adapterAnnounce.getItem(position).getId();// this will get you selected obj of itemAnnounce
String obj = (String)selectedObj.toString();
Intent i = new Intent(SuggestionMain.this, announce_Page.class);
i.putExtra("annId",obj);
startActivity(i);
}
});
});
} else {
Log.d("TAG", "No such document");
}
} else {
Log.d("TAG", "get failed with ", task.getException());
}
}
});
the error pops
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.districtapp, PID: 12764
java.lang.NullPointerException: Attempt to invoke virtual method 'java.util.Date com.google.firebase.Timestamp.toDate()' on a null object reference
at com.example.districtapp.SuggestionMain$1.lambda$onComplete$0$SuggestionMain$1(SuggestionMain.java:65)
at com.example.districtapp.-$$Lambda$SuggestionMain$1$70rkZQjkWJS7wHwVoKS2O7TV5ls.onEvent(Unknown Source:4)
at com.google.firebase.firestore.Query.lambda$addSnapshotListenerInternal$2(Query.java:1133)
at com.google.firebase.firestore.Query$$Lambda$3.onEvent(Unknown Source:6)
at com.google.firebase.firestore.core.AsyncEventListener.lambda$onEvent$0(AsyncEventListener.java:42)
at com.google.firebase.firestore.core.AsyncEventListener$$Lambda$1.run(Unknown Source:6)
at android.os.Handler.handleCallback(Handler.java:789)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
I have impression about this sort of thing when I touch firestore the first time,So i tried to start the send activity first not the view,it works out but just for once,second time it shows the same bug,I tried to finish the whole activity listview when onclick to sendpage,still dont work,
Firestore is getting the data perfectly, and after restarting the app, listview shows the data, so the function is working though.
suggest field
You are getting NullPointerException because of the following line of code:
Date date = timestamp.toDate();
And this is because the timestamp object in:
Timestamp timestamp = (Timestamp) snapshot.getData().get("createdAt");
Has the value of null. To solve this, please change the above line of code to:
if (snapshot.getDate("createdAt") != null) {
Date timestamp = snapshot.getDate("createdAt");
//Do what you need to do with this timestamp
}
Besides that, a query like this:
firebaseFirestore.collection("Suggestion").whereEqualTo("recID",recID).orderBy("createdAt", Query.Direction.DESCENDING)
Requires an index. To add such an index please check my answer from the following post:
Firestore whereEqualTo, orderBy and limit(1) not working
Related
I want to update the above record but when I update that it updates the parent (user) instead of the child.
` button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
sendNotification();
Toast.makeText(MainActivity2.this, str, Toast.LENGTH_SHORT).show();
HashMap<String, Object> m = new HashMap<String, Object>();
Intent intent = getIntent();
String ID=intent.getStringExtra("counter");
String email = intent.getStringExtra("email");
m.put("ID",ID);
m.put("Email", email);
if(s!="Query" && s!="Resource")
m.put("Complain", t.getText().toString());
else if(s!="Complain" && s!="Resource")
m.put("Query", t.getText().toString());
else
m.put("Resources",t.getText().toString());
m.put("Time", "");
m.put("Feedback", "Pending");
FirebaseDatabase.getInstance().getReference().child("User").updateChildren(m).addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void unused) {
Toast.makeText(MainActivity2.this, "Your data is successfully updated", Toast.LENGTH_SHORT).show();
}
});
}
});`
DB structure:
I want to update the above record but when I update that it updates the parent (user) node instead of the child.
That's the expected behavior since your calling updateChildren() on the following reference:
FirebaseDatabase.getInstance().getReference().child("User");
Which points exactly to the User node. If you want to update the child, you have to add the key to the reference:
DatabaseReference db = FirebaseDatabase.getInstance().getReference();
DatabaseReference childRef = db.child("User").child("-N2gd...8-6b"); 👈
childRef.updateChildren(m).addOnSuccessListener(/* ... /*);
So the key to solving this problem is to add the key of the node in your reference. If you didn't store the key yet, then please check the answer from the following post:
How to get a key of an object that was pushed just now in Firebase?
This is like my first or second StackOverflow question, so bear with me.
I want to get the Firebase UID upon login success. However, I get an error with getCurrentUser.getUid() being null.
Below is the following code
mAuth.signInWithEmailAndPassword(inputemail.getText().toString(), inputPassword.getText().toString())
.addOnCompleteListener(Login.this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
mUser=mAuth.getCurrentUser();
userID = mUser.getUid();
DocumentReference docRef = db.collection("userDB").document(userID);
docRef.get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
#Override
public void onComplete(#NonNull Task<DocumentSnapshot> task) {
if (task.isSuccessful()) {
DocumentSnapshot document = task.getResult();
String val = document.getString("type");
if(val.equals("client")){
if (mAuth.getCurrentUser().isEmailVerified()){
progressDialog.dismiss();
sendUserToNextActivity();
Toast.makeText(Login.this, "Login Success!", Toast.LENGTH_SHORT).show();
}else{
progressDialog.dismiss();
FirebaseAuth.getInstance().signOut();
Toast.makeText(Login.this, "Please verify email first!", Toast.LENGTH_SHORT).show();
}
}else{
FirebaseAuth.getInstance().signOut();
progressDialog.dismiss();
Toast.makeText(Login.this, "Employees are not permmitted!", Toast.LENGTH_SHORT).show();
}
} else {
}
}
});
}
});
Here is the full error log.
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.bottomnavigationview, PID: 27109
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String com.google.firebase.auth.FirebaseUser.getUid()' on a null object reference
at com.example.bottomnavigationview.Login$3$1.onComplete(Login.java:86)
at com.google.android.gms.tasks.zzi.run(com.google.android.gms:play-services-tasks##18.0.1:1)
at android.os.Handler.handleCallback(Handler.java:789)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
Which points at
userID = mUser.getUid();
Is there another way or a fix where I can get the UID upon successful login? I heard about onAuthStateChanged but I can't seem to get a grasp of it.
[Edit]
It is noted that mAuth and mUser has been declared within the class.
FirebaseAuth mAuth; FirebaseUser mUser;
As well as mAuth=FirebaseAuth.getInstance() within onCreate.
Your code assumes that the sign-in succeeded, which is not necessarily the case inside onComplete.
You need to handle both success and failure, like this:
mAuth.signInWithEmailAndPassword(inputemail.getText().toString(), inputPassword.getText().toString())
.addOnCompleteListener(Login.this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
mUser=mAuth.getCurrentUser();
userID = mUser.getUid();
...
}
else {
Log.e("Firebase", "Sign in failed", task.getException());
}
}
...
Now if the sign-in fails, check the logcat output for the root cause, and fix that.
I'm getting this error when i create new user on firebase from my sign-up form :
java.lang.NullPointerException: Can't pass null for argument 'pathString' in child()
I search about this error on google and on YouTube but i don't found something for my program.
Here is a part of my code on SignUpActivity.java:
final EditText email = findViewById(R.id.email_address);
final EditText display_name = findViewById(R.id.display_name);
final EditText password = findViewById(R.id.pass_sign_up);
final EditText comfirm_pass = findViewById(R.id.comfirm_pass);
final Button submit = findViewById(R.id.submit_btn_signup);
final TextView signin = findViewById(R.id.textView8);
final FirebaseAuth mAuth = FirebaseAuth.getInstance();
final String[] error = new String[1];
final ProgressBar loading_icon = findViewById(R.id.progressBar2);
// hide loading icon \\
loading_icon.setVisibility(View.GONE);
signin.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(SignupActivity.this,MainActivity.class);
startActivity(intent);
}
});
submit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
loading_icon.setVisibility(View.VISIBLE);
String email_input = email.getText().toString();
String display_name_input = display_name.getText().toString();
String password_input = password.getText().toString();
String comfirm_pass_input = comfirm_pass.getText().toString();
if (email_input.isEmpty() || display_name_input.isEmpty() || password_input.isEmpty() || comfirm_pass_input.isEmpty()){
error[0] = "Please fill all the values and try again";
Toast.makeText(SignupActivity.this, error[0], Toast.LENGTH_LONG).show();
loading_icon.setVisibility(View.GONE);
}else{
if (!password_input.equals(comfirm_pass_input)){
error[0] = "passwords do not match";
Toast.makeText(SignupActivity.this, error[0], Toast.LENGTH_LONG).show();
loading_icon.setVisibility(View.GONE);
}else{
mAuth.createUserWithEmailAndPassword(email_input,password_input).addOnCompleteListener(new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull #NotNull Task<AuthResult> task) {
if (task.isSuccessful()){
finish();
// set display name for user \\
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
UserProfileChangeRequest profileUpdates = new UserProfileChangeRequest.Builder()
.setDisplayName(display_name_input).build();
user.updateProfile(profileUpdates);
DatabaseReference mRef = FirebaseDatabase.getInstance().getReference();
mRef.addValueEventListener(new ValueEventListener(){
#Override
public void onDataChange(#NotNull DataSnapshot dataSnapshot){
// Get the max_user_id to set the main user id and create the user on Firebase real-time DB \\
String maxUserId = dataSnapshot.child("max_user_id").getValue().toString();
int maxUserIdToInt = Integer.parseInt(maxUserId);
int userId = maxUserIdToInt+1;
newUserId = String.valueOf(userId);
mRef.child("users").child(newUserId).child("name").setValue(display_name_input);
}
#Override
public void onCancelled(#NotNull DatabaseError databaseError){
Toast.makeText(SignupActivity.this,"error: " + databaseError, Toast.LENGTH_LONG).show();
}
});
mRef.child("users").child(newUserId);
Intent intent = new Intent(SignupActivity.this,HomeActivity.class);
startActivity(intent);
}else{
loading_icon.setVisibility(View.GONE);
error[0] = "failed to sign up, the email address aleready exist or the password lenght is lower than 6 characters";
Toast.makeText(SignupActivity.this, error[0], Toast.LENGTH_LONG).show();
}
}
});
}
}
}
});
}
}
NOTE: i'm beginner on firebase for android applications. Also i created today my account here and stackoverflow is so cool and helpfull
When you call child(), you need to pass a non-null String as the parameter. In your case, newUserId is null for some reason. Hence you call child(newUserId), Firebase throws an exception.
The way forward should be check if the way you are accessing child with path max_user_id is correct or not. You can keep a breakpoint at that location and then go through the structure of dataSnapshot to get the correct path.
The problem is in the last line in this fragment:
DatabaseReference mRef = FirebaseDatabase.getInstance().getReference();
mRef.addValueEventListener(new ValueEventListener(){
#Override
public void onDataChange(#NotNull DataSnapshot dataSnapshot){
// Get the max_user_id to set the main user id and create the user on Firebase real-time DB \\
String maxUserId = dataSnapshot.child("max_user_id").getValue().toString();
int maxUserIdToInt = Integer.parseInt(maxUserId);
int userId = maxUserIdToInt+1;
newUserId = String.valueOf(userId);
mRef.child("users").child(newUserId).child("name").setValue(display_name_input);
}
#Override
public void onCancelled(#NotNull DatabaseError databaseError){
Toast.makeText(SignupActivity.this,"error: " + databaseError, Toast.LENGTH_LONG).show();
}
});
mRef.child("users").child(newUserId);
That line does nothing meaningful, but it executes before newUserId = String.valueOf(userId), which means you're passing in an initialized newUserId and that causes the error messages.
Since this line mRef.child("users").child(newUserId); does nothing anyway, you can safely remove it.
As a general rule: you should only use the newUserId inside the onDataChange or in code that is called from there. For this reason, I recommend making it a local variable in onDataChange instead of a field or otherwise broader scope. For more on why this is, see Is it possible to synchronously load data from Firebase? and Setting Singleton property value in Firebase Listener.
This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 2 years ago.
My app is getting some errors whenever I click the signout button. I suspect that this causes by the authentication.signout().
This is the error:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.demo.finalssuncrestbank, PID: 17982
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String com.google.firebase.firestore.DocumentSnapshot.getString(java.lang.String)' on a null object reference
at com.demo.finalssuncrestbank.UserProfile$1.onEvent(UserProfile.java:52)
at com.demo.finalssuncrestbank.UserProfile$1.onEvent(UserProfile.java:49)
at com.google.firebase.firestore.DocumentReference.lambda$addSnapshotListenerInternal$2(DocumentReference.java:483)
at com.google.firebase.firestore.DocumentReference$$Lambda$3.onEvent(Unknown Source:6)
at com.google.firebase.firestore.core.AsyncEventListener.lambda$onEvent$0(AsyncEventListener.java:42)
at com.google.firebase.firestore.core.AsyncEventListener$$Lambda$1.run(Unknown Source:6)
at android.os.Handler.handleCallback(Handler.java:790)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:169)
at android.app.ActivityThread.main(ActivityThread.java:6521)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
The code is this:
DocumentReference documentReference = fStore.collection("Users").document(UserID);
documentReference.addSnapshotListener(this, new EventListener<DocumentSnapshot>() {
#Override
public void onEvent(#Nullable DocumentSnapshot value, #Nullable FirebaseFirestoreException error) {
mName.setText("Name: " + value.getString("Name"));
mPhone.setText("Phone: " + value.getString("Phone"));
mEmail.setText("Email: \n \n" + value.getString("Email"));
mBalance.setText(String.valueOf(value.getDouble("Balance")));
}
});
LogOut.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
fAuth.signOut();
Intent intent = new Intent(getApplicationContext(), Login.class);
startActivity(intent);
}
});
I wanted to know what are the possible reasons why this keeps happening and what should I do?
You are accessing UI in your listener. The listener will listen to any changes forever or in your user log out listener, you are navigating to another Activity which mean the current Activity/UI is null and the listener addSnapshotListener will be triggred as there is a change in authorisation state.
You must detach your snapshot listener before sending your intent: https://firebase.google.com/docs/firestore/query-data/listen#java_11
DocumentReference documentReference = fStore.collection("Users").document(UserID);
ListenerRegistration registration = documentReference.addSnapshotListener(this, new EventListener<DocumentSnapshot>() {
#Override
public void onEvent(#Nullable DocumentSnapshot value, #Nullable FirebaseFirestoreException error) {
mName.setText("Name: " + value.getString("Name"));
mPhone.setText("Phone: " + value.getString("Phone"));
mEmail.setText("Email: \n \n" + value.getString("Email"));
mBalance.setText(String.valueOf(value.getDouble("Balance")));
}
});
LogOut.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Stop listening to changes
registration.remove();
fAuth.signOut();
Intent intent = new Intent(getApplicationContext(), Login.class);
startActivity(intent);
}
});
When it logout, again it notifies in addSnapshotListener. But this time FirebaseFirestoreException. So make sure before accesing value if there is no error.
DocumentReference documentReference = fStore.collection("Users").document(UserID);
documentReference.addSnapshotListener(this, new EventListener<DocumentSnapshot>() {
#Override
public void onEvent(#Nullable DocumentSnapshot value, #Nullable FirebaseFirestoreException error) {
if( error == null){
mName.setText("Name: " + value.getString("Name"));
mPhone.setText("Phone: " + value.getString("Phone"));
mEmail.setText("Email: \n \n" + value.getString("Email"));
mBalance.setText(String.valueOf(value.getDouble("Balance")));
}
}
});
LogOut.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
fAuth.signOut();
Intent intent = new Intent(getApplicationContext(), Login.class);
startActivity(intent);
}
});
In my app users are able to send text and images to other users and now i also want when a user clicks on the sent or received image they will be taken to another activity were the image will be loaded into an image view for the user.
So i added a click listener to the image in my adapter like this
void bind(Messages message) {
String message_type = message.getType();
String user_id = message.getFrom();
String msg_id = message.getKey();
if (message_type.equals("text")) {
messageText.setText(message.getMessage());
// Format the stored timestamp into a readable String using method.
timeText.setText(DateUtils.formatDateTime(message.getTime()));
// DatabaseReference messageRef = mRootRef.child("messages").child(mCurrentUserId).child(user_id).child()
recieved_image.setVisibility(View.INVISIBLE);
// nameText.setText(message.getSender().getNickname());
// Insert the profile image from the URL into the ImageView.
// Utils.displayRoundImageFromUrl(mContext, message.getSender().getProfileUrl(), profileImage);
}else {
messageText.setVisibility(View.INVISIBLE);
recieved_image.setVisibility(View.VISIBLE);
Picasso.with(recieved_image.getContext()).load(message.getMessage()).into(recieved_image);
recieved_image.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(view.getContext(), MessageImageViewerActivity.class);
intent.putExtra("message_id",msg_id);
view.getContext().startActivity(intent);
}
});
with the aim of transferring the message id to the next activity which should be used to locate and load the image from firebase storage like this
msgImage = findViewById(R.id.MsgImageView);
mAuth = FirebaseAuth.getInstance();
final String message_id = getIntent().getStringExtra("message_id");
mRootRef = FirebaseDatabase.getInstance().getReference();
mCurrentUserId = mAuth.getCurrentUser().getUid();
mImageStorage.child("message_images").child(message_id).getDownloadUrl().addOnCompleteListener(new OnCompleteListener<Uri>() {
#Override
public void onComplete(#NonNull Task<Uri> task) {
if (task.isSuccessful()){
String ima = task.getResult().toString();
// Picasso.with(MessageImageViewerActivity.this).load(ima).into(msgImage);
Glide.with(MessageImageViewerActivity.this)
.load(ima)
.into(msgImage);
}
}
});
but it is returning an error that the path is invalid. this is the logcat error message.
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'com.google.firebase.storage.StorageReference com.google.firebase.storage.StorageReference.child(java.lang.String)' on a null object reference
at com.mani.eric.quickchat.ui.MessageImageViewerActivity.onCreate(MessageImageViewerActivity.java:60)
at android.app.Activity.performCreate(Activity.java:7327)
at android.app.Activity.performCreate(Activity.java:7318)
please what I'm trying to do, is it possible?
or what I'm i not doing right.
You need to do the following:
StorageReference mImageStorage = FirebaseStorage.getInstance().getReference();
First get the reference to the firebase storage, then access the child that you created in the firebase storage console.
mImageStorage.child("message_images").child(message_id).getDownloadUrl().addOnCompleteListener(new OnCompleteListener<Uri>() {
#Override
public void onComplete(#NonNull Task<Uri> task) {
if (task.isSuccessful()){
String ima = task.getResult().toString();
// Picasso.with(MessageImageViewerActivity.this).load(ima).into(msgImage);
Glide.with(MessageImageViewerActivity.this)
.load(ima)
.into(msgImage);
}
}
});