How to separate four users in the firebase in android? - java

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).

Related

Updating data in firebase realtime database

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?

Firebase Android error: Can't pass null for argument 'pathString' in child

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.

Firebase Login should go to Home Screen if user already exists [duplicate]

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

Android: How to login an user with his phone number

I'm creating an app with where I want already signed up users to be redirected to their profile if their phone number is registered in the app, but if he is a new user then he will be redirected to the welcome page.
The problem is, I'm able to get the verification code for the phone number, but it is always redirecting to the welcome page irrespective of whether it is an existing user or a new user.
By far I've implemented Firebase phone authentication, and
private void verifyCode(String code) {
PhoneAuthCredential phoneAuthCredential = PhoneAuthProvider.getCredential(verificationId, code);
signInWithCredentials(phoneAuthCredential);
}
private void signInWithCredentials(PhoneAuthCredential phoneAuthCredential) {
mAuth.signInWithCredential(phoneAuthCredential).addOnCompleteListener(new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
final String num = getIntent().getStringExtra("phoneNumber");
final Query query = FirebaseDatabase.getInstance().getReference("users").orderByChild("birthday").equalTo(num);
if (task.isSuccessful()) {
if (num.equals(query.toString())) {
Log.i("Method", "Inside if block");
Log.i("value", num + query.toString());
Intent intent = new Intent(VerifyPhoneActivity.this, WelcomeActivity.class);
startActivity(intent);
} else {
Log.i("Method", "Inside if block2");
Log.i("value", num + query.toString());
Intent intent = new Intent(VerifyPhoneActivity.this, ProfileActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
}
} else {
Toast.makeText(VerifyPhoneActivity.this, task.getException().getMessage(), Toast.LENGTH_LONG).show();
}
}
});
}
I'm taking only the phone number of the user to log in/sign up, and there's no separate button for login and sign up. It should work in such a way that, once the OTP sent by the Firebase auth has been verified and if the phone number is already present in the database, it should directly fo the user's profile page instead of the welcome screen, however, if the phone number is new it should go to the welcome page instead of the user profile page.
The challenge I'm facing is I'm not able to check if the number entered is already present in the database in the user table(I've created a separate user table to store the details of the user when he signs up for the first time).
from what I understood you're able to register users but you're not able to redirect unregistered users to the login/signup screen, if that's the case then you can try to use
FirebaseAuth.getInstance().currentUser
in the on create view method in your welcome/home page it should be something like this
override fun onCreate(savedInstanceState: Bundle?) {
if (FirebaseAuth.getInstance().currentUser == null) {
startActivity(Intent(applicationContext, RegistrationActivity::class.java))
finish()
return
}
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// do your other stuff
}
this code is written in kotlin it shouldn't be that different in java. hope it helps.
UPDATE------
you have a few mistakes with your code, try this
private void verifyCode(String code) {
PhoneAuthCredential phoneAuthCredential = PhoneAuthProvider.getCredential(verificationId, code);
FirebaseAuth.getInstance().signInWithCredential(phoneAuthCredential).addOnCompleteListener(new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
final String num = getIntent().getStringExtra("phoneNumber");
FirebaseDatabase.getInstance().getReference("users").orderByChild("phoneNumber").equalTo(num).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
Intent intent = new Intent(VerifyPhoneActivity.this, ProfileActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
} else {
FirebaseDatabase.getInstance().getReference("users").push().child("phoneNumber").setValue(num).addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
Intent intent = new Intent(VerifyPhoneActivity.this, WelcomeActivity.class);
startActivity(intent);
}
});
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
} else {
Toast.makeText(VerifyPhoneActivity.this, task.getException().getMessage(), Toast.LENGTH_LONG).show();
}
}
});
}
first of all, you have to log in the user with the phone detail then you check if you have any user registered with that phone number if you do then that means that this user has already entered the app but if you didn't have any information of user with that phone number then you create his information and direct him to the welcome screen after creating his information, so if this user comes back again you will check if we have a record of user with that phone number (which we do) so this time he will be directed to the profile screen

Return to Mainactivity if Firebase Database has no children

I"m stuck in one problem. My firebase structure is given in image where subject is the child value i get using intent extra on click from button
consider I have two buttons Button A and Button B
when I press Button A then it will sent subject as string value of "Bhaktapur" and now I have details of Bhaktapur in Recycleview but when I clcik Button B if it pass an string value "xyz" then I have no any value with data "xyz" then It should return to Mainactivity with Toast message " Not Found"
But The first one works fine and recycleview is updated with information but on second case I have progress Dialog keeps loading untill I cancel it.
Here is my code
dbreference =
FirebaseDatabase.getInstance().getReference("books").child(subject);
dbreference.addListenerForSingleValueEvent(new
ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
for (DataSnapshot data : snapshot.getChildren()) {
if (!data.exists()) {
progressDialog.dismiss();
Toast.makeText(SubjectBooks.this, "No books
found!", Toast.LENGTH_SHORT).show();
Intent in = new Intent(SubjectBooks.this,
MainActivity.class);
startActivity(in);
finish();
} else {
final Books b1 = data.getValue(Books.class);
// Log.e("Value is ",dataSnapshot.getKey()+"
"+b1.getBauthor());
//Log.e("Book"," received");
child_count++;
list.add(b1);
staggeredBooksAdapter.notifyDataSetChanged();
progressDialog.dismiss();
}
}
}
Any help is appreciated. Thanks in advance.
I clcik Button B if it pass an string value "xyz" then I have no any
value with data "xyz" then It should return to Mainactivity with Toast
message " Not Found"
Because no data found against xyz, for loop will not be executed neither if-else.As you are dismissing the progress bar inside if-else, it will keep showing indefinitely. So you've to check if DataSnapshot exist before for loop as follows
dbreference.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
if (snapshot.exists()) {
// TODO: handle the case where the data exists
for (DataSnapshot data : snapshot.getChildren()) {
final Books b1 = data.getValue(Books.class);
// Log.e("Value is ",dataSnapshot.getKey()+"
"+b1.getBauthor());
//Log.e("Book"," received");
child_count++;
list.add(b1);
staggeredBooksAdapter.notifyDataSetChanged();
progressDialog.dismiss();
}
}
else {
// TODO: handle the case where the data does not yet exist
progressDialog.dismiss();
Toast.makeText(SubjectBooks.this, "No books
found!", Toast.LENGTH_SHORT).show();
Intent in = new Intent(SubjectBooks.this,
MainActivity.class);
startActivity(in);
finish();
}
}
#Override
public void onCancelled(FirebaseError firebaseError) { }
});

Categories

Resources