I am pretty new to Firebase and have a question.
I'm looking to link my new authenticated user to a database that I have working.
I have class named addChild which contains an editText for add children's name, and need this to be linked to the authenticated user on a database. So when that user logs in, they can see their children's names that they have inputted.
Does anybody know how I could do this? I have set up the real-time database connection Im just not sure where to go from here.
Thanks
This is how I created user.
auth.createUserWithEmailAndPassword(email, password)
.addOnCompleteListener(CreateUserAccount.this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
Toast.makeText(CreateUserAccount.this, "User Account Created" + task.isSuccessful(), Toast.LENGTH_SHORT).show();
// If sign in fails, display a message to the user. If sign in succeeds
// the auth state listener will be notified and logic to handle the
// signed in user can be handled in the listener.
if (!task.isSuccessful()) {
Toast.makeText(CreateUserAccount.this, "Authentication failed." + task.getException(),
Toast.LENGTH_SHORT).show();
} else {
startActivity(new Intent(CreateUserAccount.this, LandingPage.class));
finish();
}
}
});
After you authenticate a user using Firebase Authentication, then also you can send his uid to the database:
FirebaseUser user=FirebaseAuth.getInstance().getCurrentUser();
String useruid=user.getUid();
then in the database you would have this:
Users
useruid
name: userx
email: userx#gmail.com
String name = editText.getText().toString();
String email = editTxt.getText().toString();
DatabaseReference ref=FirebaseDatabase.getInstance().getReference().child("Users").child(useruid);
ref.child("name").setValue(name);
ref.child("email").setValue(email);
Edit:
} else {
FirebaseUser user= task.getResult().getUser();
DatabaseReference ref=FirebaseDatabase.getInstance().getReference().child("Users").child(user.getUid());
ref.child("name").setValue(name);
ref.child("email").setValue(email);
startActivity(new Intent(CreateUserAccount.this, LandingPage.class));
finish();
}
to add the children in the other activity:
First retrieve the names from an edittext
then add them like this:
Children
useruid <--- the id that is in the usernode above
childname: john
useruid
childname: james bond
Related
Register Button in Register Acvtivity
public void registerBtnClicked(View view){
String email = binding.userEmailEditText.getText().toString();
String password = binding.userPasswordEditText.getText().toString();
String userNameData = binding.usernameEditText.getText().toString();
user = new Users(userNameData,email,password);
db = FirebaseDatabase.getInstance();
databaseReference = db.getReference(Users.class.getSimpleName());
databaseReference.push().setValue(user);
if(email.equals("") || password.equals("")){
Toast.makeText(this, "Enter email and password", Toast.LENGTH_LONG).show();
}else{
auth.createUserWithEmailAndPassword(email,password).addOnSuccessListener(new OnSuccessListener<AuthResult>() {
#Override
public void onSuccess(AuthResult authResult) {
Intent intent = new Intent(RegisterPage.this, MainActivity.class);
startActivity(intent);
finish();
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(RegisterPage.this, e.getLocalizedMessage(),Toast.LENGTH_LONG).show();
}
});
}
}
I created a real time database.But I couldn't figure out how to show username in navigation header section. Can you help me?
If I understand correctly, the firebaseUser is null when you're trying to read the display name from it. This is actually a common scenario, as the user's sign-in session is managed by Firebase in the background, and the current user may change at any time.
The simple fix is to check whether there is a current user before accessing their display name, which you can do with:
firebaseUser = FirebaseAuth.getInstance().getCurrentUser();
if (firebaseUser != null) {
navUserEmail.setText(firebaseUser.getEmail());
navUserName.setText(firebaseUser.getDisplayName());
}
Note though that the display name is an optional property of the user profile, so it can indeed be null. If you want to display nothing in that case, you can do:
String displayName = firebaseUser.getDisplayName();
navUserName.setText(displayName != null ? displayName : "");
Even if you've set the display name of a user, it may take up to an hour until that is updated for all connected clients, as they all cache the user profile. And since such updates happen in the background... 👇
To correctly handle all auth state changes, you'll want to use an auth state listener, as shown in this article: https://stackoverflow.com/collectives/google-cloud/articles/68104924/listen-for-authentication-state-in-android
What I am trying to achieve is when a new user registers I would like to run a query to make sure that the username which they have selected doesn't already belong to some other user. To do this I have written the register(); method, but it's not giving me back anything, not the Toast message indicating that the username has already been taken, nor does it take me to the next page indicating that the email has been sent and the user has to now log in.
Can someone explain to me what I am doing wrong?
RegisterActivity
private void register(final String username, final String fullname, String email, String password) {
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Users");
reference.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
boolean ifUsernameExists = false;
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
User user = snapshot.getValue(User.class);
if (user != null) {
if (username.equals(user.getUsername())) {
Toast.makeText(RegisterActivity.this, "That username has already been taken. Try another", Toast.LENGTH_SHORT).show();
ifUsernameExists = true;
}
}
}
if (!ifUsernameExists) {
mAuth.createUserWithEmailAndPassword(email, password).addOnCompleteListener(RegisterActivity.this, task -> {
if (task.isSuccessful()) {
sendVerificationEmail();
FirebaseUser firebaseUser = mAuth.getCurrentUser();
String userid = firebaseUser.getUid();
mReference = FirebaseDatabase.getInstance().getReference().child("Users").child(userid);
HashMap<String, Object> hashMap = new HashMap<>();
hashMap.put("id", userid);
hashMap.put("email", email);
hashMap.put("username", username.toLowerCase());
hashMap.put("fullname", fullname);
hashMap.put("bio", "");
hashMap.put("imageurl", "https://firebasestorage.googleapis.com/v0/b/events-50eda.appspot.com/o/Placeholder.png?alt=media&token=0e651fa8-32e9-4f42-be9a-a5365f44b0f4");
mReference.setValue(hashMap).addOnCompleteListener(task1 -> {
if (task1.isSuccessful()) {
FirebaseAuth.getInstance().signOut();
Intent intent = new Intent(RegisterActivity.this, LoginActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
});
} else {
Toast.makeText(RegisterActivity.this, "You can't register with that email", Toast.LENGTH_LONG).show();
mProgressDialog.dismiss();
}
});
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
The value that you are looking for in the user variable is getting lost. I would print it out ar run a debug to check where I am losing it.
The first part of the problem was solved according to OP's comment:
I figured out that actually my entire problem was Firebase rules.
Using the information in the answer from the following post:
Checking if a particular value exists in the Firebase database
What if I just wanted to use a for loop and look through all the usernames?
You cannot do that unless you are authenticated.
Like I said the method I wrote works, I just need to make it so an unauthenticated user can read to see if the username could possibly exist and then write to the database, meaning save their data to Firebase.
The only way in which unauthenticated users can read the data is to write the rules like this:
{
"rules": {
".read": true,
".write": true
}
}
But is not recommended because these security rules are defined as public, and anyone can steal, modify, or delete data in your database.
The simplest solution I can think of is to authenticate the user with email and password and provide the option the set the user name right after that. Once the user is already authenticated, you can use the query that you said it's working along with the existing security rules.
I want to check when a user attempts to signup with createUserWithEmailAndPassword() in Firebase user Authentication method, this user is already registered with my app.
To detect whether a user with that email address already exists, you can detect when the call to createUserWithEmailAndPassword () fails with auth/email-already-in-use. I see that #Srinivasan just posted an answer for this.
Alternatively, you can detect that an email address is already used by calling fetchSignInMethodsForEmail().
The usual flow for this is that you first ask the user to enter their email address, then call fetchSignInMethodsForEmail, and then move them to a screen that either asks for the rest of their registration details (if they're new), or show them the provider(s) with which they're signed up already.
When the user trying to create an user with same email address, the task response will be "Response: The email address is already in use by another account."
mFirebaseAuth.createUserWithEmailAndPassword(email,password)
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if(task.isSuccessful()){
//User registered successfully
}else{
Log.i("Response","Failed to create user:"+task.getException().getMessage());
}
}
});
First of all, you need to make sure you have that restriction enabled in Firebase console (Account and email address settings). Take a look at #Srinivasan's answer.
Then, do this in your java code:
firebaseAuthenticator.createUserWithEmailAndPassword(email, password)
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if (!task.isSuccessful()) {
if (task.getException() instanceof FirebaseAuthUserCollisionException) {
Toast.makeText(SignUpActivity.this, "User with this email already exist.", Toast.LENGTH_SHORT).show();
}
} else {
sendVerificationEmail();
startActivity(new Intent(SignUpActivity.this, DetailsCaptureActivity.class));
}
// ...
}
});
This is where the trick happens:
if (task.getException() instanceof FirebaseAuthUserCollisionException) {
Toast.makeText(SignUpActivity.this,
"User with this email already exist.", Toast.LENGTH_SHORT).show();
Several exceptions can be thrown when registering a user with email and password, but the one we are interested in is the FirebaseAuthUserCollisionException. As the name implies, this exception is thrown if the email already exists. If the exception thrown is an instance of this class, let the user know.
As a practice of #Frank's answer here is the code of using fetchProvidersForEmail()
private boolean checkAccountEmailExistInFirebase(String email) {
FirebaseAuth mAuth = FirebaseAuth.getInstance();
final boolean[] b = new boolean[1];
mAuth.fetchProvidersForEmail(email).addOnCompleteListener(new OnCompleteListener<ProviderQueryResult>() {
#Override
public void onComplete(#NonNull Task<ProviderQueryResult> task) {
b[0] = !task.getResult().getProviders().isEmpty();
}
});
return b[0];
}
I was looking into this kind of condition where we can detect if user exists or not and perform registration and login. fetchProvidersForEmail is best option right now. I have found this tutorial. Hope it helps you too!
See : Manage Users
UserRecord userRecord = FirebaseAuth.getInstance().getUserByEmail(email);
System.out.println("Successfully fetched user data: " + userRecord.getEmail());
This method returns a UserRecord object for the user corresponding to the email provided.
If the provided email does not belong to an existing user or the user cannot be fetched for any other reason, the Admin SDK throws an error. For a full list of error codes, including descriptions and resolution steps, see Admin Authentication API Errors.
private ProgressDialog progressDialog;
progressDialog.setMessage("Registering, please Wait...");
progressDialog.show();
mAuth.createUserWithEmailAndPassword(email, password)
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
//checking if success
if (task.isSuccessful()) {
//Registration was successfull:
Toast.makeText(RegistrationActivity.this, "Successfully registered!", Toast.LENGTH_LONG).show();
} else {
//Registration failed:
//task.getException().getMessage() makes the magic
Toast.makeText(RegistrationActivity.this, "Registration failed! " + "\n" + task.getException().getMessage(), Toast.LENGTH_LONG).show();
}
progressDialog.dismiss();
}
});
Add below code to MainActivity.java file.When user attempt to register with the same email address a message "The email address is already used by another account" will pop up as a Toast
mAuth.createUserWithEmailAndPassword(email,password).addOnCompleteListener(new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if(!task.isSuccessful()){
Toast.makeText(MainActivity.this, task.getException().getMessage(), Toast.LENGTH_SHORT).show();
}
if(task.isSuccessful()){
Toast.makeText(MainActivity.this, "Sign up successfull", Toast.LENGTH_SHORT).show();
}
}
});
You do not have to do anything because the backend of Firebase will do the job.
Unless you are referring to reauthenticating of the app.
Take a scenario for an example, w
I want to add a feature in my app that allows the admin account to delete firebase user accounts from inside the app. I have the user Id that I want to delete stored in a String but can't get the user record from the firebase auth database using the Id.
The getUser() method stays in red and android studio shows a note :
Cannot resolve method getUser(java.lang.String).
I already tried searching on the net for previous similar problems but they were all trying to delete the connected user and not a specific user of a given ID
// getIntent() is a method from the started activity
Intent myIntent = getIntent(); // gets the previously created intent
final String UserId = myIntent.getStringExtra("uid"); // will return "User Id"
final Button btnDelete = findViewById(R.id.deleteaccount);
final FirebaseUser userToDelete = FirebaseAuth.getInstance().getUser(UserId);
btnDelete.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
userToDelete.delete().addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()){
Toast.makeText(TAG, "Account deleted", Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(TAG, task.getException().getMessage(), Toast.LENGTH_SHORT).show();
}
}
})
}
});
I want to achieve one goal: Being able to delete a user with a given Id.
The Firebase web and mobile client libraries don't support the ability to get and delete user accounts, as that would pose a security risk. The only way to programmatically manage user accounts is using the Firebase Admin SDK to on a backend you control.
I am creating an android app that registers a user to firebase Authentication. So as you can see below this is the program i made to give you a hint on what i am referring . . .
public void createAccount(final String email, final String password, final String firstname, final String lastname)
{
mAuth.createUserWithEmailAndPassword(email, password)
.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, "createUserWithEmail:success");
FirebaseUser user = mAuth.getCurrentUser();
UserInformation UInfo = new UserInformation(user.getUid(), user.getEmail(), password, firstname, lastname);
newRef = database.getReference("Users");
newRef.child(user.getUid()).setValue(UInfo);
//newRef.child(user.getUid()).child("id").setValue(user.getUid());
Toast.makeText(Signup.this, "User registered: " + user.getEmail(), Toast.LENGTH_LONG).show();
} else {
// If sign in fails, display a message to the user.
Log.w(TAG, "createUserWithEmail:failure", task.getException());
Toast.makeText(Signup.this, "Authentication failed.",
Toast.LENGTH_SHORT).show();
}
}
});
}
after register succeeds all other devices also gets affected as well, in terms of, all the other devices prompts as if they've just logged in again.
my problem is, why does it do that? why does all other devices gets affected as if they've just logged in again. what's causing the issue?
also, this is my database rules.
{
"rules": {
".read": true,
".write": true
}
}