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?
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.
This question already has answers here:
How to redirect multiple types of users to their respective Activities?
(3 answers)
Checking if a particular value exists in the Firebase database
(6 answers)
Closed 2 years ago.
First, I will tell the flow of my App.
Login Screen(SignInActivity.java) -> Enter details(MainActivity.java) ->Home Screen(HomeScreenActivity.java)
In my app, I have used Firebase Authentication and Firebase Database. When the user is new, then it should go to Main Activity from SignInActivity where user enters his name, a short description and his hobby. The details are stored in Firebase Database and then HomeScreenActivity opens where user details are shown in Recycler View.
But currently what happens is when same user does login again, it again asks user for details. I want to check if users Google Account already exists in Firebase Auth, then instead of asking details, it should directly go to HomeScreenActivity.
I checked many answers on StackOverflow, but nothing seems to work. One thing that i tried was additionalUserInfo.isNewUser but in this app crashes when user does login again, showing null error where I display user details in HomeScreenActivity.
SignInActivity.java
private void firebaseAuthWithGoogle(String idToken) {
AuthCredential credential = GoogleAuthProvider.getCredential(idToken, null);
mAuthIn.signInWithCredential(credential)
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
// Sign in success, update UI with the signed-in user's information
Log.d(TAG, "SignInWithCredential:success");
startActivity(new Intent(SignInActivity.this, MainActivity.class));
finish();
} else {
// If sign in fails, display a message to the user.
Toast.makeText(SignInActivity.this, "Authentication Failed", Toast.LENGTH_SHORT).show();
}
}
});
}
MainActivity.java
public void init() {
hobbiesContinueButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String name=user.getText().toString().trim();
String desc=description.getText().toString().trim();
String hobby=spinner.getSelectedItem().toString();
String image="default";
String thumbnail="default";
if(!TextUtils.isEmpty(name))
{
FirebaseUser currentUser = FirebaseAuth.getInstance().getCurrentUser();
assert currentUser != null;
String userId=currentUser.getUid();
User user=new User(name,hobby,desc,image,thumbnail);
dbRef.child(userId).setValue(user);
startActivity(new Intent(getApplicationContext(), HomeScreenActivity.class));
finish();
}
else
{
Toast.makeText(getApplicationContext(), "Enter a name",Toast.LENGTH_SHORT).show();
}
}
});
}
HomeScreenActivity.java
dbRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
imgvw = headerView.findViewById(R.id.imageView);
imgvw.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//to open gallery
Intent galleryIntent = new Intent();
galleryIntent.setType("image/*");
galleryIntent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(galleryIntent, "SELECT IMAGE"), GALLERY_PICK);
}
});
TextView nameDrawer = findViewById(R.id.navName);
TextView descDrawer = findViewById(R.id.navDescription);
User change = snapshot.getValue(User.class);
assert change != null;
//This is where null error occurs
nameDrawer.setText(change.getUserName());
descDrawer.setText(change.getUserDesc());
//change profile picture
image= Objects.requireNonNull(snapshot.child("userImage").getValue()).toString();
Log.d(TAG, "onComplete: "+image);
if(!image.equals("default")){
Picasso.get().load(image).placeholder(R.drawable.avatar).into(imgvw);
}
}
The solution is to save your user details in shared preferences for the first time when the user sign in , then after the user signs out and sign it again , you get data from shared preferences and set them directly to your edittexts
Try this Code :
///save sharedpreferences
SharedPreferences sharedPreferences =
getSharedPreferences("prefs",Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString("username","put here your username"); //
editor.putString("email","put your email here"); //you can add more details
editor.apply();
///get sharedpreferences
SharedPreferences sharedPreferences1 =
getSharedPreferences("prefs",Context.MODE_PRIVATE);
String username = sharedPreferences1.getString("username","");
String email = sharedPreferences1.getString("email","");
//then here set the valeus from sharedpreferences to your edittexts
I'm using Firebase for login, but I want the user to also be added to the Real-Time Database so I can link the User with further data.
When a user registers, I can see that the user has been added to the authentication section of Firebase, and the user is able to log in but it does not get added to the Real-Time Database.
Here is my code
db = FirebaseDatabase.getInstance();
users = db.getReference("Users");
User user = new User();
user.setEmail((editEmail.getText().toString()));
user.setPassword((editPass.getText().toString()));
user.setName((editName.getText().toString()));
user.setPhone(editPhone.getText().toString());
users.child(FirebaseAuth.getInstance().getCurrentUser().getUid())
.setValue(user)
I also set an onSuccess/fail listener with Toasts letting me know if it failed or not. And neither of the toasts execute. I do have read/write enabled on my DB.
Define Variable.
private DatabaseReference userRef;
in OnCreate method.
userRef = FirebaseDatabase.getInstance().getReference().child("Users");
in a signup button
String getUserName = usernameEditText.getText.toString;
String getBio = bioEditText.getText.toString;
//and you should use the validates
if(getUserName.equals("")
{
usernameEditText.setError("Field Required");
}
else if(getBio.equals("")
{
bioEditText.setError("Field Required");
}
else
{
final HashMap<String , Object> profileMap = new HashMap<>();
profileMap.put("uid" , FirebaseAuth.getInstance().getCurrentUser().getUid());
profileMap.put("name" , getUserName);
profileMap.put("status" , getBio);
userRef.child(FirebaseAuth.getInstance().getCurrentUser().getUid())
.updateChildren(profileMap)
.addOnCompleteListener(new OnCompleteListener<Void>()
{
#Override
public void onComplete(#NonNull Task<Void> task)
{
if (task.isSuccessful())
{
Log.v("Profile Updated" , "Profile Updated Successfully");
Intent intent = new Intent(SettingsActivity.this , MainActivity.class);
startActivity(intent);
finish();
progressDialog.dismiss();
Toast.makeText(SettingsActivity.this, "Your profile Info has been updated", Toast.LENGTH_SHORT).show();
}
}
});
}
I was wondering if there was a way to edit the name and email via code in Android Studio, to change it in Cloud Firestore. I made a program where it only changes the name in real-time and when logged off, and logged in again it changes back to the previous one which is in Cloud Firestore.
vardas is an EditText field in the app design.
My code:
public void updateProfile(final View view) {
view.setEnabled(false);
vardas1 = vardas.getText().toString();
FirebaseUser firebaseUser = FirebaseAuth.getInstance().getCurrentUser();
UserProfileChangeRequest request = new UserProfileChangeRequest.Builder()
.setDisplayName(vardas1)
.build();
firebaseUser.updateProfile(request)
.addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
view.setEnabled(true);
Toast.makeText(Profile.this, "SÄ—kmingai atnaujintas profilis", Toast.LENGTH_SHORT).show();
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
view.setEnabled(true);
Log.e(TAG, "onFailure: ", e.getCause());
}
});
}
I was wondering if there was a way to edit the name and email via code in Android Studio, to change it in Cloud Firestore.
Yes, there is. According to the official documentation regarding how to update a document in Cloud Firestore:
To update some fields of a document without overwriting the entire document, use the update() method.
Assuming you want to update the name and email of the authenticated user that exists at the following reference:
String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
FirebaseFirestore rootRef = FirebaseFirestore.getInstance();
CollectionReference usersRef = rootRef.collection("users");
DocumentReference uidRef = usersRef.document(uid);
Try the following lines of code:
uidRef.update(
"name", "John",
"email", "john#email.com"
).addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
Log.d(TAG, "DocumentSnapshot successfully updated!");
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.w(TAG, "Error updating document", e);
}
});
The result of using this is code, is the update of the name property with "John".
What you are doing in your code is nothing else than updating the name in the FirebaseUser object. That operation is not related in any way with Firestore. So updating the FirebaseUser it doesn't mean that the user will be also updated in the Firestore database. There are two different separate operations that are not related.