I am trying to retrieve data from the firebase realtime database and save it to a variable like this:
mUserDatabase.child(mCurrentUserId).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
myPublicKeyString = dataSnapshot.child("public_key").getValue().toString();
myPrivateKeyString = dataSnapshot.child("private_key").getValue().toString();
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Where myPublicKeyString and myPrivateKeyString are global variables. When I try to do a System.out.println(myPublicKeyString); inside the ValueEventListener function it does indeed print out the correct data but when I try to do the same outside of the function it prints out null.
Related
private TextView welcomeText;
DatabaseReference databaseReference = database.getReference("Users").child("name");
https://i.stack.imgur.com/Qayc6.png
What I want to do is retrieve the data "name" from the Firebase database and setText for the welcomeText to the data "name".
Try this
DatabaseReference reference = FirebaseDatabase.getInstance().getReference();
reference.child("Users").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
for (DataSnapshot dataSnapshot : snapshot.getChildren()) {
//model class assign
ModelClass Class = dataSnapshot.getValue(ModelClass.class);
String name = cartClass.getName();
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
Hey I hope you going fantastic. Make sure you have inserted your DB URL from Firebase in your FirebaseDatabase object in your code before coding the query.
So in order your project is ready you need to read the following path: DB > users > UserID > name to reach the value you are looking for. If you want to change 'name' into all of your firebase database registers you should try this.
DatabaseReference reference = FirebaseDatabase.getInstance('FirebaseDBURL').getReference();
reference.child("Users").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
for (DataSnapshot dataSnapshot : snapshot.getChildren()) {
//Here you are reading all of your Users objects
if(dataSnapshot.getKey.equals('name')){ //Here we are identifying the attr you want to change by its key name
String text = reference.child("Users").child(datasnapshot.getValue()).getValue(String.class);
yourEditText.setText(text);
}
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
I hope you solve your issue. However here you have such an usefull info:`
So I made a void function that should put some values in an array . I call the function , then I call the array variable and it crashes saying that its null. I am also using firebase to get all the values .
This is the Function :
private void findRestaurantKey()
{
mDatabase = FirebaseDatabase.getInstance();
mDatabaseReference = mDatabase.getReference("x");
mDatabaseReference.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
int i = 0;
for (DataSnapshot d : dataSnapshot.getChildren()) {
allRestNames[i] = d.getKey();
i++;
}
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
And here is how i try to call it :
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.food_activity);
this.findRestaurantKey();
Log.d("ARRAY" , allRestNames.toString());
}
You need to initialize your array.
List<String> allRestNames = new ArrayList();
But if you run the code as you have it, you would not Log anything
This is what is called a 'race condition', you are running asynchronous code expecting the result to be there as soon as you call it.
When making a request to an API like you are doing using the Firebase service it takes time.
So what you should do if you wanna Log the results is do it in the callback:
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.food_activity);
findRestaurantKey();
}
private void findRestaurantKey() {
mDatabase = FirebaseDatabase.getInstance();
mDatabaseReference = mDatabase.getReference("x");
mDatabaseReference.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
for (DataSnapshot d : dataSnapshot.getChildren()) {
allRestNames.add(d.getKey());
}
// HERE is when the data is available from the Firebase service
Log.d("ARRAY" , allRestNames.toString());
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
You need to initialize your array somewhere:
allRestNames = new String[5000];
Use whatever number is appropriate instead of 5000. If you don't know what size to make the array to begin with, you should use an ArrayList instead of an array.
Also, findRestaurantKey() creates a listener for your Firebase database. When this method returns, the data is not yet available because the listener has not yet been called. So even if you solve the current error, you will not get any meaningful data from calling allRestNames.toString() in onCreate().
This is my database. I want to check if a particular uid exists before adding so that I can avoid duplicate entries of the same uid. This is my code. It checks if the uid exists and then returns a boolean. which is parsed into an if statement in another method to add the contact. However, this method only returns false, even if the uid already exists in the contacts. Therefore allowing the adding of the same entry.
The method to check if contact exists.
public void addContacts(final String emailInput){
DatabaseReference users;
users = FirebaseDatabase.getInstance().getReference("users");
users.orderByChild("email").equalTo(emailInput).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
final DatabaseReference ref = FirebaseDatabase.getInstance().getReference("users");
for (DataSnapshot emailSnapshot : dataSnapshot.getChildren()) {
String emailData = emailSnapshot.child("email").getValue(String.class);
final String name = emailSnapshot.child("name").getValue(String.class);
String role = emailSnapshot.child("role").getValue(String.class);
if (emailData.equals(emailInput)){
key = emailSnapshot.getKey();
System.out.println(key);
if ((!role.equals(userRole))) {
DatabaseReference contactRef = ref.child(FirebaseAuth.getInstance().getCurrentUser().getUid()).child("contacts").child(key);
contactRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (!dataSnapshot.child(key).exists()) {
ContactProfile newContact = new ContactProfile(key, name);
ref.child(FirebaseAuth.getInstance().getCurrentUser().getUid()).child("contacts").push().setValue(newContact);
Toast.makeText(Contacts.this, "Contact Added Successfully", Toast.LENGTH_SHORT).show();
}
else {
Toast.makeText(Contacts.this, "Contact Already Exists", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
else if(key.equals(FirebaseAuth.getInstance().getCurrentUser().getUid())){
Toast.makeText(Contacts.this, "You cannot add yourself",Toast.LENGTH_SHORT).show();
}
else{
Toast.makeText(Contacts.this, "Cannot add user. \n They have the same role",
Toast.LENGTH_SHORT).show();
}
}
else {
Toast.makeText(Contacts.this, "Cannot add user. \n User does not exist",
Toast.LENGTH_SHORT).show();
}
}
}
Although i have no idea about firebase , but the problem might occur due to that you are using method inner class so the scope of value is out of this assignment ,and again you are comparing out of the method inner class so the value=1 will not happen it will always be value=0 so condition will never get true.
Try this...
DatabaseReference contactRef = userRef.child("Users").child(FirebaseAuth.getInstance().getCurrentUser().getUid()).child("contacts").child(key);
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(dataSnapshot.exists()) {
value = 1;
}
}
Data is loaded from Firebase asynchronously. It is easiest to see what this means if you place a few log statements:
System.out.println("Before attaching listener");
contactRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
System.out.println("Got data");
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
throw databaseError.toException(); // don't ignore errors
}
});
System.out.println("After attaching listener");
When you run this code, it prints:
Before attaching listener
After attaching listener
Got data
This is probably not what you expected, but it explains exactly why your code doesn't work: by the time you check if (value.equals(1)){, the onDataChange method hasn't run yet.
As you see there is no way we can return the value from the database. Any return statement outside of onDataChange will run before the data has been loaded. And any return statement we run within onDataChange won't be able to return data to the calling function.
The quickest solution is to move all code that needs the data into the onDataChange method:
private boolean contactExists(final String key){
DatabaseReference userRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference contactRef = userRef.child("users").child(FirebaseAuth.getInstance().getCurrentUser().getUid()).child("contacts").child(key);
contactRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()){
... do what we need to do is the key exists
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
throw databaseError.toException(); // don't ignore errors
}
});
}
If you want to make the approach a bit more reusable, you can define your own callback interface and pass that into your contactExists. For an example of this, see my answer here: getContactsFromFirebase() method return an empty list
I want to fetch data from inside Firebase to check whether this user exists in database but there's a problem that i can't solve , listener trigger late this is my code :-
if I remove while loop i can't fetch object fast
if I keep while loop i enter infinite loop , i don't know why
why listener don't trigger
DataSnapshot fetched ;
public boolean user_exist(final String user) throws Exception {
users.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
fetched = dataSnapshot ;
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
while (fetched == null){
Log.e("dbController","not fetched yet");
}
return fetched.hasChild(user);
}
Firebase has to fetch the data from database and bring it in your app. This may take time, hence it should be done in background. When you add valueEventListener, the fetching is done in background. You may display a progressBar to show data is still loading, and once data is in hands, do the rest of code:
users.child(user).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
funUserExists();
} else {
funNoUser();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
ANDROID: I have a Firebase database like this.
In my app, I would like to compile an arraylist that displays all values from the nameofEntry [DESCRIBED BELOW]. By this I mean the "balso," the "nairboh" and so on.
I have the references:
DatabaseReference root = FirebaseDatabase.getInstance().getReference();
DatabaseReference users = root.child("Users");
DatabaseReference childRef = users.child(userID);
DatabaseReference childRefNameNode = childRef.child(nameOfEntry);
childRefNameNode.child(nameOfEntry).setValue(nameOfEntry);
//FETCH DATA
childRefNameNode.child(nameOfEntry).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String valueFromDB = dataSnapshot.getValue(String.class);
Log.i("Jimit", valueFromDB);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
But this only fetches for one entry. How can I get more entries? [All of them]?
You need to use this code snippet. You haven't used any for loop to step over your children.
EDIT: Also, update your database reference as:
//Updated ref
DatabaseReference ref = FirebaseDatabase.getInstance().getReference().child("Users").child(userID);*
//add listener to updated ref
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
//use the for loop here to step over each child and retrieve data
for (DataSnapshot childSnapshot : dataSnapshot.getChildren()){
String valueFromDB = childSnapshot.getValue(String.class);
Log.i("Jimit", valueFromDB);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Do let me know if it changes anything for you.