Firebase-Database inconsistence data being stored on database in Android - android

I'm new to firebase. i'm trying to store some data in Firebase-database in the given format:
approot{
uid{
name:"name"
add:"add"
phn:"phn"
}
uid2{
name:"name"
add:"add"
phn:"phn"
}
.......
and so on.
for this i have written the following code:
String phn = inputPhn.getText().toString().trim();
String add = inputAdd.getText().toString().trim();
String name = inputName.getText().toString().trim();
if (TextUtils.isEmpty(name)) {
Toast.makeText(getApplicationContext(), "Enter name!", Toast.LENGTH_SHORT).show();
return;
}
if (TextUtils.isEmpty(phn)||phn.length()!=10) {
Toast.makeText(getApplicationContext(), "Enter phone no.!", Toast.LENGTH_SHORT).show();
return;
}
if (TextUtils.isEmpty(add)) {
Toast.makeText(getApplicationContext(), "Enter address!", Toast.LENGTH_SHORT).show();
return;
}
//String info="Name:"+name+"\n"+"PhoneNo:"+phn+"\n"+"Adress:"+add+"\n";
String uId=auth.getCurrentUser().getUid();
myref.child(uId).child("name").setValue(name);
myref.child(uId).child("add").setValue(add);
myref.child(uId).child("phone").setValue(phn);
myref.child(uId).child("end").setValue("end");
auth.signOut();
my problem is that i'm getting in-consistent data storage in firebase database. the data stored in database is this :
{
"User" : {
"ANj8GLEJS9alW11QYQyF8Rykwyn2" : {
"add" : "hzjs",
"name" : "hxjx"
},
"b0ZBftQ5UOOtTtzkeZHcC0558MC3" : {
"add" : "gw",
"name" : "hs"
},
"eH6rCXzvEncTe163N7KaJ7XEZp52" : {
"name" : "dudj"
},
"gEqc92Z0mvcfIWvhZu7QOhRcnNQ2" : {
"add" : "bsus",
"name" : "jziz",
"phone" : "1234567890"
},
"kGF2PalHrpeFus6682z55p47YBg2" : {
"add" : "hdud",
"name" : "jdhd"
},
"nHRt5n5roGfU3QogVUM09HDBrIw2" : {
"add" : "qwerty",
"end" : "end",
"name" : "q",
"phone" : "1234567860"
},
"pRRzexjQN1eynoCQcoClNl2TcHk2" : {
"add" : "dvjh",
"name" : "rhid"
},
"vaek3Z4eEVTWmc722T92tfgBwaE3" : {
"add" : "dhudvj",
"name" : "gsbud"
},
"xsH5JoTXftaxicUmvntt0N5hcNJ3" : {
"add" : "zhs",
"name" : "q"
}
}
}
please help me.
Edit
i'm using firebase 9.2.1.
and the rules defined are:-
{
"rules": {
".read": "auth != null",
".write": "auth != null"
}
}

You should wait for the setValue to finish before you sign out the user, because the auth will be null after the signOut successfully called. If the setValue haven't finished, it will violate your rule because the auth has been null.
You can use a CompletionListener to make sure that the setValue is completed, then you can safely sign out the user. Like this
Map<String, String> values = new HashMap<>();
values.put("name", name);
values.put("add", add);
values.put("phone", phn);
values.put("end", end);
DatabaseReference.CompletionListener completionListener = new DatabaseReference.CompletionListener() {
#Override
public void onComplete(DatabaseError databaseError, DatabaseReference databaseReference) {
auth.signOut();
}
};
myref.child(uid).setValue(values, completionListener);

Related

Firebase Iterate through entire database

I am trying to receive all the data from a firebase database, so I can place it into a Users class however I do not know how I will iterate through the entire database as I cannot interger (the i variable in the for loop) insert values into the child field.
My code is this:
myRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if(dataSnapshot.exists())
{
String fullname = (String) dataSnapshot.child(userId).child("Fullname").getValue();
String country = (String) dataSnapshot.child(userId).child("Country").getValue();
String profilePicture = (String) dataSnapshot.child(userId).child("ProfilePicture").getValue();
String username = (String) dataSnapshot.child(userId).child("Username").getValue();
Toast.makeText(getApplicationContext(), "Testing with: " + fullname + country + profilePicture + username, Toast.LENGTH_SHORT).show();
Toast.makeText(getApplicationContext(), "Count : (4) - " + dataSnapshot.getChildrenCount(), Toast.LENGTH_SHORT).show();
showProfiles(dataSnapshot);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
Database:
{
"Users" : {
"4PdlTlv3qjZ3BmDvrJyUut9Fnq43" : {
"Country" : "xx",
"Fullname" : "hh",
"ProfilePicture" : "htm/o/Images%2FSearchAdapter%2F4PdlTlv3qjZ3BmDvrJyUut9Fnq43%2FProfilePicture%2FProfilePic_2019.03.06.10.47.54.jpg.jpg?alt=media&token=b647708e-c6d5-4b45-bef0-3dc40301b73a",
"Username" : "hmack001"
},
"COg4r4io9hezhFpmK3adPucUXA93" : {
"Country" : "spain",
"Fullname" : "nat",
"ProfilePicture" : "hcom/o/Images%2FSearchAdapter%2FCOg4r4io9hezhFpmK3adPucUXA93%2FProfilePicture%2FProfilePic_2019.03.06.19.14.17.jpg.jpg?alt=media&token=8620b321-5cef-42f0-a828-dbb7c37c8e7d",
"Username" : "nat"
},
"Tw1xRxViygNsLqrQiaaMAvAduIu1" : {
"Country" : "uk",
"Fullname" : "harvey\n",
"ProfilePicture" : "t.com/o/Images%2FUsers%2FTw1xRxViygNsLqrQiaaMAvAduIu1%2FProfilePicture%2FProfilePic_2019.03.03.05.26.35.jpg.jpg?alt=media&token=c290e75a-5f92-4271-bcb5-c644fe1b14ef",
"Username" : "RGB"
},
"vOxr1RoDqgWogKK1lp9pfpTHc6w2" : {
"Country" : "scotland ",
"Fullname" : "greg greg",
"ProfilePicture" : "ot.com/o/Images%2FSearchAdapter%2FvOxr1RoDqgWogKK1lp9pfpTHc6w2%2FProfilePicture%2FProfilePic_2019.03.04.12.30.22.jpg.jpg?alt=media&token=27b024cf-0691-4121-8a27-26acf101ebc2",
"Username" : "greg"
},
"xecUOPeyMcQaQrgkU9ouDgK90Ai1" : {
"Country" : "ggh",
"Fullname" : "Da apply ",
"ProfilePicture" : "2FProfilePic_2019.03.03.04.58.50.jpg.jpg?alt=media&token=f35854c2-3ff9-4d18-9f7a-10c13f066c68",
"Username" : "gg"
}
}
}
I am aware that there is no attempt in this code to retrieve information from all the users fields, I do not understand the logic behind iterating through the database as I dont see where I can do Item 1, Item 2 etc.
Use this
for (DataSnapshot childSnapshot : dataSnapshot.getChildren()) {
System.out.println(childSnapshot.getKey());
System.out.println(childSnapshot.child("Country").getValue(String.class));
}

android: adding a new node

Need to add a new node "Completed" under the parent which will eventually contain all the information from the node "Requests" at end of the ride.
So basically, I need to create node "Completed" first but its not adding it.
database
{
"Requests" : {
"iowpxU6WKUWpzWJyfssSoOVCPFj2" : {
".priority" : "f8118c3k3v",
"destination" : "221 Prince William St",
"details" : {
"driver" : "nYIAHSYimJMHbMkXqDt9PQ0U3Nf2",
"location" : "27 Horsfield St",
"request status" : "accepted",
"ridePrice" : 3.75,
"rideStatus1" : "arrived at pickup",
"rideStatus2" : "rider in vehicle",
"rideStatus3" : "destination bound",
"rideStatus4" : "arrived at destination",
"rider" : "iowpxU6WKUWpzWJyfssSoOVCPFj2",
"riderPaid" : "true"
},
"Users" : {
"Drivers" : {
"nYIAHSYimJMHbMkXqDt9PQ0U3Nf2" : {
"driver" : "nYIAHSYimJMHbMkXqDt9PQ0U3Nf2",
"email" : "driver#me.com",
"name" : "driver",
"password" : "whatever",
"phone" : "5551212",
"rates" : "0"
}
},
"Riders" : {
"iowpxU6WKUWpzWJyfssSoOVCPFj2" : {
"avatarUrl" : "",
"email" : "rider#me.com",
"name" : "rider",
"password" : "whatever",
"phone" : "5551313",
"rates" : "0",
"riderId" : "iowpxU6WKUWpzWJyfssSoOVCPFj2"
}
}
}
}
addNewNode
private void addNewNode() { // TODO: ........ NOT ADDING NEW NODE :-| ..........
Toast.makeText(this, "addNewNode", Toast.LENGTH_LONG).show();
DatabaseReference newNode = FirebaseDatabase.getInstance().getReference("Completed");
newNode.child(riderId).push().addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Toast.makeText(DriverTripDetail.this, "addNewNode: onDataChange", Toast.LENGTH_LONG).show();
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
Any assistance on how I can fix this would be greatly appreciated.
The Firebase Database stores values at paths. If there is no value, the path does not exist.
Your code creates a reference to /Completed/$pushID. but doesn't set any value, so the path doesn't get created. Something like this will work, since it sets a value:
newNode.child(riderId).push().setValue(true)

android firebase saving data to realtime database

In android app I create a firebase user authenticated by phone number and it works fine then I update this user adding display name and this is fine too; in the end I want to save user's data into firebase database so I wrote this rule:
"users" : {
"$user_id" : { // firebase user uid
".read" : "$user_id === auth.uid",
".write" : "$user_id === auth.uid",
".validate": "newData.hasChildren(['enabled', 'group', 'name'])",
"enabled" : { ".validate" : "newData.isBoolean()" },
"group" : { ".validate" : "newData.isString()" },
"name" : { ".validate" : "newData.isString()" },
}
}
This doesn't work and I get returned "permission denied" altough the simulator shows everything is fine (in the simulation I use custom authentication and set firebase as provider with the user's uid).
the user's class is:
public class User {
public boolean enabled;
public String group;
public String name;
public User() { }
public User(boolean enabled, String group, String name) {
this.enabled = enabled;
this.group = group;
this.name = name;
}
}
and i try to save it by:
private void saveUserToDB() {
User newUser = new User(true, "operators", currentUser.getDisplayName());
mRootRef.child("users").child(currentUser.getUid()).setValue(newUser, new DatabaseReference.CompletionListener() {
#Override
public void onComplete(DatabaseError databaseError, DatabaseReference databaseReference) {
if (databaseError != null) {
Log.e("ERROR", "Data could not be saved " + databaseError.getMessage());
} else {
Log.e("SUCCESS", "Data saved successfully.");
}
}
});
}
Can anybody kindly help me to understand why this happens?
Thanks
UPDATE
below is a "schema" of how the database should be:
{
"messages" : {
"1763409620982" : { // timestamp
"position" : "position text",
"sender" : "sender name",
"text" : "message text"
},
"1763409734527" : { // timestamp
"position" : "position text",
"sender" : "sender name",
"text" : "message text"
}
...
},
"users" : {
"Yi79w0HgA4ZTNAMHadixzoO5PaR2" : { // firebase user uid
"enabled" : true,
"group" : "group 1",
"name" : "user display name"
},
"kX22c0GgL4ZTNAMHallfgoO4pBN1" : { // firebase user uid
"enabled" : true,
"group" : "group 2",
"name" : "user name"
}
...
}
}
and here's the full set of rules:
{
"rules": {
"messages" : {
".read" : "root.child('users').child(auth.uid).child('group').val() === 'group 1'",
".write" : "root.child('users').child(auth.uid).child('group').val() === 'group 2'",
"$tstamp" :{
".validate": "newData.hasChildren(['position', 'sender', 'text'])",
"position" : { ".validate" : "newData.isString()" },
"sender" : { ".validate" : "newData.isString()" },
"text" : { ".validate" : "newData.isString()" },
}
},
"users" : {
"$user_id" : {
".read" : "$user_id === auth.uid",
".write" : "$user_id === auth.uid",
".validate": "newData.hasChildren(['enabled', 'group', 'name'])",
"enabled" : { ".validate" : "newData.isBoolean()" },
"group" : { ".validate" : "newData.isString()" },
"name" : { ".validate" : "newData.isString()" },
}
}
}
}
as to the class user it's defined as above and only used into the method saveUserToDB
Try to add push() before setValue(): It will add new sub-node containing all the fields from object of User class:
mRootRef.child("users").child(currentUser.getUid()).push().setValue(and so on...
May be you need write permission?:

Get a specific child from Firebase

In my Firebase, I have a database for an app. Let's say this is my Firebase JSON:
{
"Users" :{
"User1":{
"City": "Genk"
}
,"User2":{
"City": "Hasselt"
}
,"User3":{
"City": "Genk"
}
,"User4":{
"City": "As"
}
,"User5":{
"City": "Genk"
}
}
}
Now what I want is an ArrayList with all the users with city Genk. How is this possible? I want to use this ArrayList to put the specific Users who live in the city Genk in a ListView.
I suggest you create another child from the root like "UsersCity", In that way you can just call this child and retrieve it to your listview. Here's what i did:
String key = mDatabase.child("post").push().getKey();
UserPost userPost = new UserPost(author,uid,setemoticon,postData,mDate,latlng);
Map<String, Object> postValues = userPost.toMap();
Map<String, Object> childUpdates = new HashMap<>();
childUpdates.put("/post/" + key,postValues);
childUpdates.put("/user-post/" + uid + "/" + key, postValues);
mDatabase.updateChildren(childUpdates);
Here's the Json output for that :
{
"post" : {
"-KcGVPpS9CTWPNax61wf" : {
"authorName" : "Test 1",
"dateCreated" : {
"dateCreated" : 1486352395887
},
"postDescription" : "sample post",
"postEmotion" : 2130837658,
"userId" : "KTcgauWoJugXUsq6TAgrdqUvVYm1"
}
},
"user-post" : {
"KTcgauWoJugXUsq6TAgrdqUvVYm1" : {
"-KcGVPpS9CTWPNax61wf" : {
"authorName" : "Test 1",
"dateCreated" : {
"dateCreated" : 1486352395887
},
"postDescription" : "sample post",
"postEmotion" : 2130837658,
"userId" : "KTcgauWoJugXUsq6TAgrdqUvVYm1"
}
}
},
//This child node is for users where you'll want to get the $uid to use for creation of other child nodes.
"users" : {
"KTcgauWoJugXUsq6TAgrdqUvVYm1" : {
"fullname" : "Test 1"
}
}
}
I am just a newbie programmer and I know my answer is not the best but I hope it could help you out with your problem. :)
just fetch specific node data and its working perfect for me
mFirebaseInstance.getReference("yourNodeName").getRef().addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot postSnapshot : dataSnapshot.getChildren()) {
Log.e(TAG, "======="+postSnapshot.child("email").getValue());
Log.e(TAG, "======="+postSnapshot.child("name").getValue());
}
}
#Override
public void onCancelled(DatabaseError error) {
// Failed to read value
Log.e(TAG, "Failed to read app title value.", error.toException());
}
});

How to prevent duplicated uname of Users Firebase [duplicate]

This question already has answers here:
How do you prevent duplicate user properties in Firebase?
(2 answers)
Closed 6 years ago.
I am adding username for my Chat App to Firebase Database successfully.
I implemented in activity:
FirebaseDatabase firedb = FirebaseDatabase.getInstance();
in createUser Method.
private void createUser(String uname){
Map<String,Object> newUser = new HashMap<String, Object>();
newUser.put("uname",uname);
DatabaseReference dbref = firedb.getReference();
dbref.child("Users").push().setValue(newUser);
}
When user click a button this method works. This method work correctly but I want to make uname primary key. I do not want to add a username if it is alerady exists.
Database Structure:
Rules:
{
"rules": {
".read": true,
".write": true
}
}
Finally, how to prevent duplicated uname ?
You have to add a top level /uname/ Node. Your data will be like this for example :
{
"Users" : {
"user1" : {
"uname" : "value1",
},
"user2" : {
"uname" : "value2",
},
"user3" : {
"uname" : "value3",
},
},
"uname" : {
"value1": "user1",
"value2": "user2",
"value3": "user3",
}
}
Now you have to Enforce New Data Structure:
{
"rules": {
"users": {
"uname": {
".validate": "!root.child('uname').child(newData.val()).exists()"
},
}
}
}

Categories

Resources