Combine FirebaseAuth UserInfo from ProviderData into one comprehensive User - android

After signing in through Google and logging the data pulled from the FirebaseAuth user, this is how Firebase has you draw a user's account information:
To get the profile information retrieved from the sign-in providers linked to a user, use the getProviderData method.
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
if (user != null) {
for (UserInfo profile : user.getProviderData()) {
// Id of the provider (ex: google.com)
String providerId = profile.getProviderId();
// UID specific to the provider
String uid = profile.getUid();
// Name, email address, and profile photo Url
String name = profile.getDisplayName();
String email = profile.getEmail();
Uri photoUrl = profile.getPhotoUrl();
};
}
When I log the information pulled from each profile I get the following couple incomplete data sets:
06-08 12:48:12.851 14400-14400/com.example.app D/MainActivity: providerId: firebase, uid: 1***************2, name: null, email: d**********y#gmail.com, url: null
06-08 12:48:12.851 14400-14400/com.example.app D/MainActivity: providerId: google.com, uid: 1************5, name: D*******y, email: null, url: https://lh4.googleusercontent.com/.../photo.jpg
Is there a standard means of combining user information and storing it as a more accessible data set? FirebaseAuth (at least in this example) doesn't seem to be the most clean-cut way to retrieve user information at runtime.

There is no other way to get providerData for a currentUser. I assume you prefer to lookup data by some key such as providerId instead of traversing that list. You can always duplicate this data in realtime database using structure that you prefer such as a key/value map.

Related

how to check the current Firebase data under uid?

I am trying to check uid from firebase Realtime database, but its only returns the current uid and when I try to check uid with previous uid then also it only returns the current uid. I had tried many ways and searched but I can't get the exact solution, please if any one could help.
here what I am using to check the uid
FirebaseAuth.getInstance().getCurrentUser().getUid();
here is my code how I am trying to check
String userEnteredUserName = binding.textLoginUserName.getEditText().getText().toString().trim();
String userEnteredPassword = binding.textPassword.getEditText().getText().toString().trim();
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Users");
Query checkUser = reference.child(FirebaseAuth.getInstance().getCurrentUser().getUid()).orderByChild("userName").equalTo(userEnteredUserName);
Log.d("uids", "uid: " + uid);
checkUser.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
binding.textLoginUserName.setError(null);
binding.textLoginUserName.setErrorEnabled(false);
Log.d("users", "Username: " + snapshot.toString());
if (snapshot.exists()) {
String passwordFromDB = snapshot.child(userEnteredUserName).child("password").getValue(String.class);
if (passwordFromDB.equals(userEnteredPassword)) {
//next activity
}else{
Toast.makeText(Login.this, "Error", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
Toast.makeText(Login.this, "Error", Toast.LENGTH_SHORT).show();
}
});
In log what I get,
2022-02-06 13:13:06.173 18093-18093/abc C/uids: uid: OFtpR6bfISP3Odd9K1oGWCQmeEf2
Here is my firebase data, "aisha12" is working which is under the current uid but when I try to check "vgbb" it returns only the current uid
If I understand correctly, you are trying to allow a user to register a username and ensuring that the username is unique. Your current data structure doesn't allow you to do that query though.
Firebase Realtime Database can only order/filter on a value that is at a fixed path under each child node of the location you query. So in your current code:
reference.child(FirebaseAuth.getInstance().getCurrentUser().getUid()).orderByChild("userName").equalTo(userEnteredUserName);
You are querying the direct child nodes of /Users/$uid looking for the username under there. Since you're specifying the UID in that path, you're only searching under that specific user.
There is no way with your current data structure to search across all /Users, since the property you are looking for is under /Users/$uid/$username/userName, so with two dynamic keys in there, and the database can only handle one dynamic key.
To allow the query, you will need to change the data structure and remove the $userName level from it, so that you get:
Users: {
"3l6Rm....": {
"userName": "vgbb",
...
},
"OftpR...": {
"userName": "aisha12",
...
}
}
Now you can search for the username with:
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Users");
Query checkUser = reference.orderByChild("userName").equalTo(userEnteredUserName);
I also recommend checking out these previous questions on allowing a user to register a unique username:
How do you prevent duplicate user properties in Firebase?
Firebase security rules to check unique value of a child #AskFirebase
How to check if usernames are unique in Firebase
unique property in Firebase
How to give unique usernames from a list of usernames to the users in the firebase
Check value already exists or not in Firebase?

How do you manage your android device token generated by FCM after token expired?

I'm developing a push notification app, do you have same issue:
My app generate a FCM device token and store it in a cloud database, so I can send notification messages to a device via FCM, and my database table looks like:
userid | device_token
Mary | xxxxxxxxxxxxxxxxxxxxxxxxxxxx // token1, from Mary's first device
John | yyyyyyyyyyyyyyyyyyyyyyyyyyyy
Mary | zzzzzzzzzzzzzzzzzzzzzzzzzzzz // token2, from Mary's second device
Mary | kkkkkkkkkkkkkkkkkkkkkkkkkkkk // token, from Mary's first device
.......
After Mary reinstalled this app from her first device, a new device token generated, and it is stored with token3.
How can I remove the expired device token token1, the only information I got may only be a pair of device token and an account name.
So how do you manage your device in this situation?
If "Mary" is using the same account to log in each time in your app, even if it is a new phone or reinstalled app why do you create a new token field inside the database? Why don't you always write inside the same token field so you always have access to this field. This will also send notifications only to the phone that your user is actually using right now. So each time when the user starts the app check token, if not equal write the new one inside your database. And from the server-side take those tokens and send notifications.
Am I missing something?
To do this, I would suggest using FirebaseAuth for the SignIn and SignUp process of your application. Then use generated uid as the field ID for the user inside the Realtime Database. You can get this uid with FirebaseAuth.getInstance().getCurrentUser().getUid(). So your user Mary will always have the same uid no matter what phone she uses. Always find the user inside the database with this uid and overwrite the existing Firebase token. This also means that your "users" will not be a single line field inside the database, but a more complex and better representation of a user. You can use model classes for this like:
public class User {
public long id = 0;
public long account_id = 0;
public String account_name = "";
public String first_name = "";
public String last_name = "";
public String email_address = "";
public String password = "";
public User() {
}
}
It's up to you on how to configure this. But using models is also helping you on posting and retrieving data, like this:
Creating new user:
DatabaseReference mDatabase = FirebaseDatabase.getInstance().getReference();
mDatabase.child("users").child(FirebaseAuth.getInstance().getCurrentUser().getUid()).setValue(user);
Retrieving data from the real-time database:
DatabaseReference database = FirebaseDatabase.getInstance().getReference();
DatabaseReference databaseUsers = database.child("users");
User myUser = null;
Query usersQuery = databaseUsers.orderByChild("username").equalTo(uid); //you can use any value to order as you want, or you don't have to, there is many options for this query
usersQuery.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChanged(#NonNull DataSnapshot snapshot) {
try {
for (DataSnapshot user : snapshot.getChildren()) {
myUser = user.getValue(User.class);
}
} catch (Exception e) {
e.printStackTrace();
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
Inspired by this: Firebase Cloud Messaging - Managing Registration Tokens
When a token generated:
if Mary logged in:
add the device to the "Mary" Device Group.
store the device group id and connect the device group id to "Mary"'s profile in database.
if app server need to send notification to Mary, just send to the Device Group, the benifit is that you don't need to check if the device token is valid or not, Firebase Cloud Messaging discards invalid device tokens.
if no one logged in:
do nothing or just store the device token.

FireBase Real Time Database

I am using Firebase Database in an Android application, and everytime a user is singUp I store some values in the database for this purpose I am doing what follows:
#Override
public void writeObject(IUser object) {
User usrReal = (User) object ; // this userReal's reference same with parameter
User usrCopy = new User(usrReal); // copy of it
String usrId = usrCopy.getUserId();
databaseReference.child("usrId").setValue(usrCopy);
//databaseReference = this.databaseReference = FirebaseDatabase.getInstance().getReference().child(path) is defined beginning of the class
}
as you see in the child method if called "usrId" it create usrId directory and add all neccesary information in it. But I want to create directory for every user ,so I tried to pass usrId variable as a parameter. Howewer it doesn't work. When I debug the code debugger says that Local var usrId can not recognized.My question is How can I create nested structure in Firebase wrt. user's id.
If the userId is the id generated by firebase authentication, then you can do:
String userId = user.getUid();
this.databaseReference = FirebaseDatabase.getInstance().getReference().child("Users");
this.databaseReference.child(userId).child("name").setValue("peter");
Then you will have this structure:
Users
userId
name : peter
userId1
name : john

How to retrieve and display data from users that are logged in - Firestore

I am trying to get and display my user's information when they are logged in. (i.e: name, email, phone)
I have tried multiple snippets i have found on youtube and on stack overflow but they have failed. Most tutorials use realtime Database, which is not what i am looking for.
I have also tried making a "users" object.
private void getData(){
FirebaseFirestore db = FirebaseFirestore.getInstance();
db.collection("users")
//.document(FirebaseAuth.getInstance().getCurrentUser().getUid())
.whereEqualTo("email:", FirebaseAuth.getInstance().getCurrentUser().getUid())
.get()
.addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
for (DocumentSnapshot document : task.getResult()) {
//Toast.makeText(getApplicationContext(),document.getId() +"==>" + document.getData(),Toast.LENGTH_LONG).show();
//Toast.makeText(getApplicationContext(),""+ document.get("Email") ,Toast.LENGTH_LONG).show();
nameEdt.setText((CharSequence) document.get("First Name"));
emailEdt.setText((CharSequence) document.get("Email"));
phoneEdt.setText((CharSequence) document.get("Phone"));
}
} else {
Toast.makeText(getApplicationContext(),"No such document",Toast.LENGTH_LONG).show();
}
}
});
}
Database Structure:
I understand that documents in firestore are not associated with users, but i dont know how to set my code up so that it only retrieves data from the user that is signed in* It works fine for newly created accounts, but if i were to log out and sign in with a different user it will not update the "account/user information".
In short, how would I access and display my database information from signed in users?
Additional Notes: I am using Email and Password for authentication
To access your user data stored in Firestore, it shouldn't be as complicated as you thought, there's no queries needed, you just need to fetch the documents corresponding to the user's uid, and fetch the specific fields or do whatever you need with them, like this:
db.collection("users").document(FirebaseAuth.getInstance().getCurrentUser().getUid())
.get().addOnCompleteListener(task -> {
if(task.isSuccessful() && task.getResult() != null){
String firstName = task.getResult().getString("First Name");
String email = task.getResult().getString("Email");
String phone = task.getResult().getString("Phone");
//other stuff
}else{
//deal with error
}
});
Original Answer:
User information is not stored in the Firestore database, they are associated with the Firebase Authentication which you set up for the log in. To retrieve the related user information, you need to use the related FirebaseAuth APIs. Use this to retrieve the current log in user:
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
Then you can get the name and email with something like this:
String name = user.getDisplayName();
String email = user.getEmail();
For more information, refer to the documentation.
If FirebaseAuth doesn't resolve, that probably means you didn't follow the set up guides correctly and forgot to include the dependency in your gradle file:
implementation 'com.google.firebase:firebase-auth:17.0.0'
After a couple days head butting at trying to find a solution, i have found one that is able to retrieve user information from the database. However it is important to note that because my application is not holding a lot of data so this structure works for me.
So i was essentially on the right track, but with some lack of understanding of firebase i missed a few concepts.
private void getData(){
FirebaseFirestore db = FirebaseFirestore.getInstance();
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
final String current = user.getUid();//getting unique user id
db.collection("users")
.whereEqualTo("uId",current)//looks for the corresponding value with the field
// in the database
.get()
.addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
for (DocumentSnapshot document : task.getResult()) {
nameEdt.setText((CharSequence) document.get("firstName"));
emailEdt.setText((CharSequence) document.get("email"));
phoneEdt.setText((CharSequence) document.get("phone"));
// These values must exactly match the fields you have in your db
}
}
As mentioned before, documents do not associate with users, but you CAN link them together by creating a field in your db called "whatever your want" (i made mine uId). This is because firebase generates a unique id for each user when authenticated. By creating a field that holds that unique id you are able to retrieve the associated information in that collection.
How to create the field:
I created a "user" object that would grab the uid from my edit text. In my code, i passed the uid wherever i was creating/authenticating a new user/account.
FirebaseUser testUser = FirebaseAuth.getInstance().getCurrentUser(); //getting the current logged in users id
String userUid = testUser.getUid();
String uidInput = userUid;
User user = new User(firstNameInput,lastNameInput,uidInput);
db.collection("users").document(userUid)
.set(user)
.addOnSuccessListener(new OnSuccessListener<Void>() {
note: I believe you can also add it to your hash map if you have it done that way.

Get uid from multiple database firebase

I'm stuck in my project's major problem.
What i want is: one user is customer, the other is driver.
I have 2 databases in which customer longitude and latitude is saving and also for driver in driver's database.
I want when customer request driver application get the longitude and latitude of customer database under the uid of that current user which driver accepted.
How can I get the uid of that customer?
I've found method to access customer database
FirebaseOptions options = new FirebaseOptions.Builder()
.setApplicationId("<your application id>")
.setApiKey("<your api key>")
.setDatabaseUrl("<your DB url that ends in 'firebaseio.com/' ")
.build();
But how can I get the uid of that current user which requested.
Here is image of 2 databases
Driver uid is just for suppose and I forgot to use push() method under uid.
myDatabase.child("codes")
.addListenerForSingleValueEvent(new ValueEventListener() {
public void onDataChange(DataSnapshot dataSnapshot) {
String clubkey = dataSnapshot.getKey();
firebase_instance.limit(100).on("child_added", function(snap) {
var name = snap.key;
});

Categories

Resources