How can i get current user information by single declaration? - java

I have many activities and also it has many methods in my app and every activity needs current user information like fristname, lastname, username from firebase database. For this, I have to declare variable every time by below codes.
UserRef.child(currentUserID).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot)
{
if(dataSnapshot.exists())
{
String myProfileImage=dataSnapshot.child("username").getValue().toString();
String userfirstname=dataSnapshot.child("firstname").getValue().toString();
String userlastname=dataSnapshot.child("lastname").getValue().toString();
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
So, now the question is, Is there any way to declare these three variable in globally and it can be use in any activity ?

DISCLAIMER:
Although the approach I am about to suggest works, it is a crude approach. To tackle this problem the proper way (using FirebaseUser), look at my other answer.
You can solve this problem by using SharedPreferences. In a nutshell, when a user signs up, you save his detail into a temporary storage called SharedPreferences. Every time you need it, you can simply retrieve it with minimal lines of code.
To save user details into SharedPreferences, you can use the method below:
public void saveToSharedPreferences(String firstName, String lastName, String photoUrl) {
// declare your sharedpreferences and editor variables
SharedPreferences sharedPreferences = context.getSharedPreferences("USER", MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
// save your values
editor.putString("firstName", firstName);
editor.putString("lastName", lastName);
editor.putString("photoUrl", photoUrl);
// commit your changes
editor.apply();
}
To retrieve your values, use these lines of code:
SharedPreferences sharedPreferences = context.getSharedPreferences("USER", MODE_PRIVATE);
String firstName = sharedPreferences.getString("firstName", "not found");
String lastName = sharedPreferences.getString("lastName", "not found");
String photoUrl = sharedPreferences.getString("photoUrl", "not found");
Note that "not found" represents your placeholder String just in
case there is no data to retrieve.
I hope this helps. Merry coding!

You can get the current Firebase user using like this:
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();

You can use the FirebaseUser class to solve your problem. It has awesome functions you can use to store user profile data.
When a user logs in or signs up, get all the details you need (firstName, lastName photoUrl) from FirebaseDatabase. After getting these values, pass them into the method below:
public void saveUserData(String firstName, String lastName, String photoUrl) {
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
UserProfileChangeRequest profileUpdates = new UserProfileChangeRequest.Builder()
.setDisplayName(firstName + " "+lastName)
.setPhotoUri(Uri.parse(photoUrl))
.build();
user.updateProfile(profileUpdates)
.addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
Log.d(TAG, "User profile updated..");
}
}
});
}
Now, anytime you want to retrieve the user's profile, do this:
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
if (user != null) {
for (UserInfo profile : user.getProviderData()) {
String firstName = profile.getDisplayName().split(" ")[0];
String lastName = profile.getDisplayName().split(" ")[1];
Uri photoUrl = profile.getPhotoUrl();
}
}
I hope this helps. Merry coding!

Best way to store the logged in user information in Shared Preference. You can create an AppPreference Class and set getter and setter according to your need. I am referring an answer to set and get useful information to follow this link :- Preventing users to login again after closing the app

Related

How can I get username from real time database and show it in navigation header?

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

Tried to add a new field of data to Firebase user when registering, but no update X method in FirebaseUser.class file

I am using the Realtime database, so the users are store in the database. I am attempting to implement a 'currentLocation' field for the FirebaseUser objects so that I can eventually create a list for each user of nearby users. I was already using a HashMap to input the data, so I just added hashmap.put('currentLocation', ''); to create an empty current location field that can be updated later.
Unfortunately though I cannot find a way to set/update the currentLocation field as there is no updateCurrentLocation() method in the FirebaseUser.class. How do I add this method to this read-only file? Is this even the best way to do this?
Code:
//Dashboard.java
usedLocationClient.getLastLocation()
.addOnSuccessListener(this, new OnSuccessListener<Location>() {
#Override
public void onSuccess(Location location) {
// Got last known location. In some rare situations this can be null.
if (location != null) {
// Logic to handle location object
//get current user
final FirebaseUser fUser = FirebaseAuth.getInstance().getCurrentUser();
//Updates the firebase db user with their current location.
fUser.updateCurrentLocation(location);
//This method is not in the firebaseuser.class file but needs to be!
//fUser.updateCurrentLocation(location);
}
}
});
//RegisterActivity.java
mAuth.createUserWithEmailAndPassword(email, password)
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
// Sign in success, dismiss dialog and start register activity
progressDialog.dismiss();
FirebaseUser user = mAuth.getCurrentUser();
//Get user email and uid from auth
String email = user.getEmail();
String uid = user.getUid();
//When user is registered store user info in firebase realtime database too
//using HashMap
HashMap<Object, String> hashMap = new HashMap<>();
//put info in hasmap
hashMap.put("email", email);
hashMap.put("uid", uid);
hashMap.put("name", ""); //will add later (e.g. edit profile)
hashMap.put("currentLocation", "");
hashMap.put("onlineStatus", "online"); //will add later (e.g. edit profile)
hashMap.put("typingTo", "noOne"); //will add later (e.g. edit profile)
hashMap.put("phone", ""); //will add later (e.g. edit profile)
hashMap.put("image", ""); //will add later (e.g. edit profile)
hashMap.put("cover", ""); //will add later (e.g. edit profile)
//firebase database instance
FirebaseDatabase database = FirebaseDatabase.getInstance();
//path to store user data named "Users"
DatabaseReference reference = database.getReference("Users");
//put data within hashmap in database
reference.child(uid).setValue(hashMap);
Toast.makeText(RegisterActivity.this, "Registered...\n"+user.getEmail(), Toast.LENGTH_SHORT).show();
startActivity(new Intent(RegisterActivity.this, DashboardActivity.class));
finish();
//FirebaseUser.class Bytecode
#NonNull
public Task<Void> updateEmail(#NonNull String email) {
Preconditions.checkNotEmpty(email);
return FirebaseAuth.getInstance(this.zza()).zzn(this, email);
}
#NonNull
public Task<Void> updatePassword(#NonNull String password) {
Preconditions.checkNotEmpty(password);
return FirebaseAuth.getInstance(this.zza()).zzo(this, password);
}
#NonNull
public Task<Void> updatePhoneNumber(#NonNull PhoneAuthCredential credential) {
return FirebaseAuth.getInstance(this.zza()).zzp(this, credential);
}
#NonNull
public Task<Void> updateProfile(#NonNull UserProfileChangeRequest request) {
Preconditions.checkNotNull(request);
return FirebaseAuth.getInstance(this.zza()).zzq(this, request);
}
FirebaseUser class, has only a few fields that are related to the authentication. If you need more details about your users, you should create a POJO class to store additional data.
This data can be stored either in Cloud Firestore or in the Realtime Database so it can be later used.
Please also note, the Realtime Database doesn't store null values. Firestore does.
To update the location of the current user, you can do:
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference reference = database.getReference("Users");
reference.child(uid).child("currentLocation").setValue("the location");
Since you mention wanting to find nearby users, I recommend checking out: Query for nearby locations and https://github.com/firebase/geofire-android/

Read real-time data from Firebase

So I have come across a problem and I seem to not be able to figure it out. I am using Firebase Auth the problem with that firebase will assign a generated user id, so I have made a Realtime Database to have user info and store a unique username. Now I am having a hard time reading the username from the database. Any suggestions on how can I read the username and not the user ID generated by Firebase Auth?
//here I have it read the last 4 digits of user ID
public void readUserName(){
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
if (user != null) {
String name = user.getUid();
String lastFourDigits = "";
if (name.length() > 4)
{
lastFourDigits = name.substring(name.length() - 4);
}
else
{
lastFourDigits = name;
}
setUser.setText(lastFourDigits);
}
}
When the data is successfully written in the database, you can simply read it by creating a reference that points to the UID node (05KR...CPZ2) of the user and by attaching a listener as shown in the following lines of code:
String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference uidRef = rootRef.child("USERSINFO").child(uid);
uidRef.get().addOnCompleteListener(new OnCompleteListener<DataSnapshot>() {
#Override
public void onComplete(#NonNull Task<DataSnapshot> task) {
if (task.isSuccessful()) {
String username = task.getResult().child("username").getValue(String.class);
Log.d(TAG, username);
} else {
Log.d(TAG, task.getException().getMessage()); //Don't ignore potential errors!
}
}
});
The result in the logcat will be:
suhash
One thing to notice is that the "uid" object represents the user ID that comes from the authentication process (05KR...CPZ2).
You can create another child in your database having username and userid relations and then you can get userid from username, something like this
"userReferences": {
"myUserName1": "myUserId1",
"myUserName2": "myUserId2"
}

Querying database to make sure new users don't register with an already existing username

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.

Saving data to Firebase with a Username Reference

I am developing a quiz application whereby a User takes a quiz and after 10 questions the score is saved to a database in Firebase.
Here is my code at present:
String user_id = mAuth.getCurrentUser().getUid();
DatabaseReference current_user_db =
FirebaseDatabase.getInstance().getReference().child("Score").child(user_id);
final int score = mScore;
**databaseUserName = FirebaseDatabase.getInstance().getReference().child("Users").child(user_id).child("username");
databaseUserName.addValueEventListener(new com.google.firebase.database.ValueEventListener() {
#Override
public void onDataChange(com.google.firebase.database.DataSnapshot dataSnapshot) {
String username = dataSnapshot.getValue().toString();
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});**
//Ensures everything saves at the same time
Map newPost = new HashMap();
newPost.put("Score", score);
**newPost.put("Username", username);**
current_user_db.setValue(newPost);
The part enclosed in ** ** is where I am having some difficulties.
The user signs up to my app using FirebaseAuth, then using the UID I have stored name and username in a 'Users' realtime database.
I would like the score databse to save the final score with the username not the autogenerated UID. I'm just not sure how to get the username and then save it to the new database.
I have also attached a screenshot of how my current database looks.
I have only been using Firebase and Android Studio a few weeks so any help/links are all appreciated.
You can do something like this
final String userName = "userX";
final int score = 55;
FirebaseDatabase db = FirebaseDatabase.getInstance();
db.getReference("Score").child(userName).child("Score").setValue(score).addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
Log.d(TAG, "onSuccess: updated " + userName + "'s score (" + score + ")");
}
});
Change your String userName to a member.
String user_id = mAuth.getCurrentUser().getUid();
// you can remove child(user_id) if you want to put username directly under Score
DatabaseReference current_user_db = FirebaseDatabase.getInstance().getReference().child("Score").child(user_id);
final int score = mScore;
DatabaseReference databaseUserName = FirebaseDatabase.getInstance().getReference().child("Users").child(user_id).child("username");
databaseUserName.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
userName = dataSnapshot.getValue().toString();
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
//Ensures everything saves at the same time
Map newPost = new HashMap();
newPost.put("Score", score);
newPost.put("Username", username); // I don't think you need this.
current_user_db.child(username).setValue(newPost);
Let me know if it works.
There is no way in which you can simply use username outside onDataChange() method because this method has an asynchronous behaviour which means that is called even before you are trying to get the data from the database. A quick fix to you are problem would be to move the follwing lines of code:
Map newPost = new HashMap();
newPost.put("Score", score);
newPost.put("Username", username);
current_user_db.child(username).setValue(newPost);
Inside onDataChange() method and your problem will be solved but if you need to use the value of username outside the onDataChange() method, then you need to create your own callback and for that I recomend you see the last part of my answer from this post.

Categories

Resources