Hoping for help on a small issue:
I am trying to delete singular records that are stored in my Firebase database through my Android application.
At present, when clicking the delete button, all items are deleted, as opposed to the single record that I have clicked on.
For completeness, I have also included my updateMaintenance method, which works perfectly. As you will see in the updateMaintenance method, I have used user-based authentication in mAuth.getCurrentUser() - I want to have this for my deleteMaintenance method also.
I'm sure this is just a case of adding a small bit of code, but not too sure where to start. Thanks in advance!
private void deleteMaintenance(String maintenanceId) {
DatabaseReference drMaintenance = FirebaseDatabase.getInstance().getReference("maintenance").child(maintenanceId);
FirebaseUser user = mAuth.getCurrentUser();
String uid = user.getUid();
databaseMaintenance.child(uid).removeValue();
Toast.makeText(this, "Maintenance record has been deleted", Toast.LENGTH_LONG).show();
}
private boolean updateMaintenance(String title, String desc, String id, String primary, String secondary, String property) {
DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference("maintenance").child(id);
Maintenance maintenance = new Maintenance (id, title, desc, primary, secondary, property);
FirebaseUser user = mAuth.getCurrentUser();
String uid = user.getUid();
databaseMaintenance.child(uid).child(id).setValue(maintenance);
databaseReference.setValue(maintenance);
Toast.makeText(this, "Maintenance Updated Updated Successfully", Toast.LENGTH_LONG).show();
return true;
}
This is happening because when using the following line of code:
databaseMaintenance.child(uid).removeValue();
You are deleting everything that is beneath the maintenance -> uid node. So basically you are deleting the uid node.
To achieve what you want, you need to change the reference. So please change the above line of code with:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
rootRef.child("maintenance").child(uid).child(maintenanceId).removeValue();
Related
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/
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"
}
I want to change the user role.
I have a collection of users with the user id. Each user has fields with mail, name, role, etc.
DatabaseReference reference;
reference = FirebaseDatabase.getInstance().getReference("users");
reference.child(document.getId()).child("Role").setValue("3");
document.getId() shows the correct user id but nothing changes in the database
Database screen
Ok it was stupid mistake. I'm working on Cloud Firestore and I've tried to change to
Realtime Database
Correct
DocumentReference docfer=db.collection("users").document(document.getId());
Map<String,Object> map = new HashMap<>();
map.put("Role","3");
docfer.update(map)
Your screenshot displays a Firestore database and not a Firebase Realtime Database. Both are apart of Firebase services but are actually two totally different products. So you need to use method that are apart of Firestore SDK. To change the value of the "Role" property, please use the following lines of code:
String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
FirebaseFirestore rootRef = FirebaseFirestore.getInstance();
CollectionReference usersRef = rootRef.collection("users");
DocumentReference uidRef = usersRef.document(uid);
uidRef.update("Role", "3").addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
Log.d("TAG", "The document is updated successfully!");
}
}
});
The result will be the update of the "Role" property from "0" to "3".
Use "update" :
reference.child(document.getId()).child("Role").update("3");
than "setValue":
reference.child(document.getId()).child("Role").setValue("3");
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 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