I am working on my App, and till now the App runs fine despite some small errors. The user can sign in, login and change his profile information. In the last steps, I added a function to delete userinformation. The delete function works so the userinformation gets deleted from FirebaseAuth and the FirebaseRealtimeDatabase but the app crashes.
Before I already had problems with passing null values, maybe thats related to the problem.
Update: I changed the code and tried to implement the suggestions but its still crashing...
Logcat:
09-18 16:28:20.474 23342-23342/com.example.login E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.login, PID: 23342
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String com.example.login.UserProfil.getVorname()' on a null object reference
at com.example.login.ProfileActivity$1.onDataChange(ProfileActivity.java:59)
at com.google.firebase.database.core.ValueEventRegistration.fireEvent(com.google.firebase:firebase-database##19.0.0:75)
at com.google.firebase.database.core.view.DataEvent.fire(com.google.firebase:firebase-database##19.0.0:63)
at com.google.firebase.database.core.view.EventRaiser$1.run(com.google.firebase:firebase-database##19.0.0:55)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:234)
at android.app.ActivityThread.main(ActivityThread.java:5526)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Some part of my ProfileActivity
firebaseAuth=FirebaseAuth.getInstance();
firebaseDatabase= FirebaseDatabase.getInstance();
if (firebaseAuth.getCurrentUser() != null) {
firebaseDatabase= FirebaseDatabase.getInstance();
final DatabaseReference databaseReference = firebaseDatabase.getReference("Users").child(firebaseAuth.getUid());
databaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) ;
{
UserProfil userProfil = dataSnapshot.getValue(UserProfil.class);
profilVorname.setText(userProfil.getVorname());
profilNachname.setText(userProfil.getNachname());
profilStrasse.setText(userProfil.getStrasse());
profilHNr.setText(userProfil.getHnr());
profilPlz.setText(userProfil.getPlz());
profilStadt.setText(userProfil.getStadt());
profilLand.setText(userProfil.getLand());
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Toast.makeText(ProfileActivity.this, "Database Error", Toast.LENGTH_SHORT).show();
}
});
}else{
startActivity(new Intent(ProfileActivity.this,NavActivity.class));
}
Some part of my UpdatProfilActivity
loeschen.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
final DatabaseReference databaseReference = firebaseDatabase.getReference("Users").child(firebaseAuth.getUid());
databaseReference.removeValue();
FirebaseUser user= FirebaseAuth.getInstance().getCurrentUser();
user.delete().addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if(task.isSuccessful()){
// firebaseAuth.signOut();
// startActivity(new Intent(UpdateProfilActivity.this, MainActivity.class));
//finish();
}
}
});
}
});
This is most probably due to that the 'dataSnapshot' object is null when onDataChange() is triggered upon deletion; you can return if it is null
databaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (!dataSnapshot.exists())
return;
UserProfil userProfil = dataSnapshot.getValue(UserProfil.class);
profilVorname.setText(userProfil.getVorname());
profilNachname.setText(userProfil.getNachname());
profilStrasse.setText(userProfil.getStrasse());
profilHNr.setText(userProfil.getHnr());
profilPlz.setText(userProfil.getPlz());
profilStadt.setText(userProfil.getStadt());
profilLand.setText(userProfil.getLand());
}
When addValueEventListener is used, then it listens on every event what happened with current reference. And when you delete it then dataSnapshot in listener comes null and on getVorname() exception is thrown.
Related
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 want to start new activity when a value ("Status") change in my Database Firebase.
But i have problem because onActivityCreated is launched three times (because my onDataChange of my Listener is called several times). How can i fix this ? Thank you in advance.
//LISTEN IF THE GAME START ::
mStart = FirebaseDatabase.getInstance().getReference().child("Rooms").child(roomId).child("Proprieties").child("Status");
mStart.addValueEventListener(new ValueEventListener(){
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.getValue().equals("GAME")){
Intent intent = new Intent(WaitGameActivity.this,GameActivity.class);
startActivity(intent);
finish();
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) { }
});
And Log :
V/FA: onActivityCreated
V/FA: onActivityCreated
V/FA: onActivityCreated
You could remove the value listener once you receive an event like below:
mStart.addValueEventListener(new ValueEventListener(){
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
mStart.removeValueEventListener(this); //remove once you get the event
if (dataSnapshot.getValue().equals("GAME")){
Intent intent = new Intent(WaitGameActivity.this,GameActivity.class);
startActivity(intent);
finish();
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) { }
});
onDataChange is called multiple times in case you have not removed the listener properly and are creating a new instance of your listener in your activity every time you open it.
Call this once you recieved data:
mStart.removeValueEventListener(this)
Im trying to write on firebase realtime database via my android app using setValue() it works very well.. but i don't know how i can handle the error if something goes wrong
i tried try/catch and turning off the WIFI so the setValue function won't work
but it didn't seem to catch any exception
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference myRef = database.getReference("message");
try{
myRef.setValue("Hello, World!");
}catch(Exception e){
e.printStackTrace();
}
There are many methods you can use to handle this. You can set any of several listeners to monitor the result state of a setValue() call:
onCompleteListener()
onFailureListener()
onSuccessListener()
My personal preference is the onCompleteListener() because it allows me to simultaneously check for success and failure with minimal lines of code. Here's an implementation:
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference myRef = database.getReference("message");
myRef.setValue("Hello, World!").addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if(task.isSuccessful()) {
// handle success event
}
else {
// handle failure event
// You can get the exact exception using task.getException()
}
}
});
I hope this helps. Merry coding!
You can use Completion Callback.
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference myRef = database.getReference("message");
myRef.setValue("Hello, World!")
.addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
// Write was successful!
// ...
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
// Write failed
// ...
}
});
I get java.lang.NullPointerException: Can't pass null for argument 'pathString' in child() when my code reaches the valueEventListener although while debugging, it seems to me that the child value is not null.
Here is the image of the code:
This is how the database looks like:
Solved the problem by completely deleting the code and starting again. This time I checked with firebase github and I did it like this(mostly the same thing? i wish i knew what was wrong with my first code):
userReference = FirebaseDatabase.getInstance().getReference().child("users").child(uid);
ValueEventListener userListener = new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
//Get user object
currentUser = dataSnapshot.getValue(User.class);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Log.w(TAG, "loadPost:onCancelled", databaseError.toException());
// [START_EXCLUDE]
Toast.makeText(UserAreaActivity.this, "Failed to load post.",
Toast.LENGTH_SHORT).show();
}
};
userReference.addValueEventListener(userListener);
The only place, in the code shown, where you could get a NPE with that message is in the call:
...child("users").child(uid);
So I'd check that uid variable, work out a way to deal with such scenario (uid == null).
Simply use the following code:
String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference uidRef = rootRef.child("users").child(uid);
ValueEventListener valueEventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String country = dataSnapshot.child("country").getValue(String.class);
String city = dataSnapshot.child("city").getValue(String.class);
Log.d(TAG, country + " / " + city);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Log.d(TAG, databaseError.getMessage()); //Don't ignore errors!
}
};
uidRef.addListenerForSingleValueEvent(valueEventListener);
The output in the logcat will be the exact country and city of your user.
Use getValue(String.class) instead of getValue().toString();
You are using unnecessary for loop.You already know what user uid is.Remove for loop then try again.
So I'm trying to create a multilevel user login page for Android Studio, I have a working basic login. I added user levels to the database but my application keeps crashing. I'm using Android Studio and Firebase as backend.
Login.Class
private void checkUserType() {
DatabaseReference databaseReference = firebaseDatabase.getReference().child("Users").child(firebaseAuth.getUid());
databaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
UserProfile userProfile = dataSnapshot.getValue(UserProfile.class);
int userType = (userProfile.getUsertype());
switch (userType) {
case 0:
startActivity(new Intent(Login.this, DoctorActivity.class));
break;
case 1:
startActivity(new Intent(Login.this, MainActivity.class));
break;
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {}
});
}
This is what my database looks like:
Logcat:
Process: com.example.trixiavillarama.hope, PID: 5524
java.lang.NullPointerException: Attempt to invoke virtual method 'com.google.firebase.database.DatabaseReference com.google.firebase.database.FirebaseDatabase.getReference()' on a null object reference
at com.example.trixiavillarama.hope.Login.checkUserType(Login.java:124)
at com.example.trixiavillarama.hope.Login.checkEmailVerification(Login.java:116)
at com.example.trixiavillarama.hope.Login.access$300(Login.java:26)
at com.example.trixiavillarama.hope.Login$4.onComplete(Login.java:91)
at com.google.android.gms.tasks.zzj.run(Unknown Source:23)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
You are getting the following error:
java.lang.NullPointerException: Attempt to invoke virtual method 'com.google.firebase.database.DatabaseReference com.google.firebase.database.FirebaseDatabase.getReference()' on a null object reference
Because your firebaseDatabase object is null, you forgot to initialize it. To solve this, please add the following line of code:
FirebaseDatabase firebaseDatabase = FirebaseDatabase.getInstance();
Right before the following line of code:
DatabaseReference databaseReference = firebaseDatabase.getReference().child("Users").child(firebaseAuth.getUid());