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.
Related
In my application, I have four users--they have same user login and separate registration. If a doctor log in he will go to the the company activity. How will I make sure that the email is a patient or an doctor or company or pharmacy?
That image shows my firebase structure
Here is my code I try:
if (user != null) {
ref = FirebaseDatabase.getInstance().getReference().child("").child(user.getUid()).child("type");
ref.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String value = dataSnapshot.getValue(String.class);
if ("doctor".equals(value)) {
startActivity(new Intent(SplashActivity.this, doctor_profile.class));
finish();
} else if ("patient".equals(value)) {
startActivity(new Intent(SplashActivity.this, PatientActivity.class));
finish();
} else if ("pharmacy".equals(value)) {
startActivity(new Intent(SplashActivity.this, PharmacyActivity.class));
finish();
} else {
startActivity(new Intent(SplashActivity.this, CompanyActivity.class));
finish();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
So starting from your implementation, you need to check each child that represents a user type to find the id of your user and start the correct Activity. There are many ways to solve your problem.
A simple way would be to define a Map<String, Class> in which each key is the name of your user type on Firebase ("Company", "Doctors"...) and each value associated is the Class object of the related Activity that you want to start. An example of adding a key-value to this map would be: mMap.put("Company", CompanyActivity.class);.
Then you can add a ValueEventListener() for each user type and use the map to avoid repeating code:
if (user != null) {
DatabaseReference ref = FirebaseDatabase.getInstance().getReference(); // find the right path in which your user types live
for (Map.Entry<String, Class> entry : mMap) {
ref.child(entry.getKey()).child(user.getUid())
.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange (DataSnapshot dataSnapshot){
if (dataSnapshot.getValue() != null) { // if value isn't null, then user is of this type and it's possible to start the correct activity
Intent i = new Intent(SplashActivity.this, entry.getValue());
startActivity(i);
finish();
}
}
#Override
public void onCancelled (DatabaseError databaseError){
}
});
}
}
This implementation keeps the single login.
If the user has signed in at least one time, you could think about storing its type in the preferences and then check directly the right child in RealTime Database (this is possible only if he doesn't have to log in again, in which case, obviously, you don't know which e-mail the user is going to use).
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.
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.
I have a system of chat in my Android application, using Firebase realtime Database. I added the option to add an image to a message, using Firebase Storage. The problem is, that after I just uploaded the data about the message, and still not the image, a ValueEventListener is called and updates the messages in the chat, when the image is still not fully uploaded. There is any way to tell Firebase when to send an update to all the listeners?
This is my code for uploading to Firebase:
final DatabaseReference postsReference = databaseReference.child(DEBUG.getPostsPath());
postsReference.child("NumberOfPosts").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
int num = dataSnapshot.getValue(Integer.class)+1;
DatabaseReference newPostReference = postsReference.child("PostNumber" + num);
newPostReference.child("Username").setValue(firebaseAuth.getCurrentUser().getDisplayName());
newPostReference.child("Post").setValue(post);
DatabaseReference idRef = newPostReference.child("id");
String key = idRef.push().getKey();
idRef.setValue(key);
if (imagePath != null) {
String id = getUniqueID();
FirebaseStorage storage = FirebaseStorage.getInstance();
StorageReference ref = storage.getReference();
StorageReference imageRef = ref.child(DEBUG.getPostsImagesPath() + "/" + id);
imageRef.putBytes(toByteArray(imagePath));
newPostReference.child("Image").setValue(id);
}
if (father != null) newPostReference.child("Father").setValue(father); //Set the ID of is father
postsReference.child("NumberOfPosts").setValue(num);
}
#Override public void onCancelled(#NonNull DatabaseError databaseError) { }
});
Is there is any function to do that??
Listeners always fire immediately after any changes are see at the location of the query. There is no way to tell the SDK to delay the callback. Your code should probably complete the upload first before writing anything to the database.
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
// ...
}
});