Getting values from Firebase - java

I'm new to Firebase, and decided to get my feet wet. However, I'm having trouble retrieving values from a query. I'm basically trying to get the password value, but I believe it's returning nothing.
Error:
java.lang.NullPointerException: println needs a message
loginButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String username = usernameField.getText().toString();
String password = passwordField.getText().toString();
db.child("Users").orderByChild("username").equalTo(username).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
//Get the password,and check it against the password field
Map<String, String> map = (Map<String, String>)dataSnapshot.getValue();
Log.d("result", map.get("password"));
} else {
Toast.makeText(getApplicationContext(), "Incorrect login details", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
});
I know this isn't very practical, but like I said I'm only practicing.
Thanks for the help!

When you execute a query against the Firebase Database, there will potentially be multiple results. So the snapshot contains a list of those results. Even if there is only a single result, the snapshot will contain a list of one result.
The code in your onDataChange needs to take care of the fact that the snapshot is a list, by looping over its snapshot.getChildren():
db.child("Users").orderByChild("username").equalTo(username).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot: dataSnapshot.getChildren()) {
//Get the password,and check it against the password field
Map<String, String> map = (Map<String, String>)snapshot.getValue();
Log.d("result", map.get("password"));
}
}

Sine your database structure is different than your reference in your code you should change some things
First your Reference to the data should be like this
db.child("Users").child(uid).child("password").addValueEventListener...
Where uid is the result of
private FirebaseAuth mAtuh;
mAuth = FirebaseAuth.getCurrentUser().getUid();
String uid = mAuth ;
Check the official doc on how to properly authenticate users
https://firebase.google.com/docs/auth/android/manage-users
Also you can implement google sign-in :
https://firebase.google.com/docs/auth/android/google-signin
And then you can retrieve your password field like this
// Attach a listener to read the data
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String password = dataSnapshot.getValue(String.class);
Log.e("The password is:",""+password);
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.e("Error getting the password",""+databaseError.getCode());
}
});
Hardcoding your reference without mAuth will be like this
db.child("Users").child("L7VR2mGZKnbReFqOlmP").child("password").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
String password = dataSnapshot.getValue(String.class);
Log.e("The password is:",""+password);
}else
{
Toast.makeText(getApplicationContext(), "Incorrect login details", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.e("Error getting the password",""+databaseError.getCode());
}
});
Hope it helps
happy coding

Related

How to retrieve push() valued data from Firebase to android

I am going to make a simple app and I am completely new to Android development. I want to develop an edit button to save my data in the Realtime Database. This is my code:
holder.edite.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final DialogPlus dialogPlus=DialogPlus.newDialog(holder.title.getContext())
.setContentHolder(new ViewHolder(R.layout.dialogcontent))
.setExpanded(true,2100)
.create();
View myView=dialogPlus.getHolderView();
EditText title=myView.findViewById(R.id.hTitle);
EditText description=myView.findViewById(R.id.hDescription);
Button submit=myView.findViewById(R.id.usubmit);
title.setText(myItems.getName());
description.setText(myItems.getAddHomeworkDescription());
dialogPlus.show();
submit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Map<String,Object> map=new HashMap<>();
map.put("name",title.getText().toString());
map.put("addHomeworkDescription",description.getText().toString());
DatabaseReference myRef = getInstance().getReference().child("Homework");
String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
// String key = myRef.push().getKey();
myRef.child(uid).child()
.updateChildren(map);
dialogPlus.dismiss();
}
});
}
});
This is how my firebase database looks like
What I want to add into .child() to get highlighted(In the image) Unique id direction. But this unique ID is not always same. It change everythime when user create new one.
You will either have to know the push key (-NN...) value of the node you want to update already, determine it with a query, or loop over all child nodes and update them all.
Update a specific child with a known push key
myRef.child(uid).child("-NNsQO7O9lh0ShefShV")
.updateChildren(map);
Update children matching a specific query
Say that you know you want to update the node with name "test12", you can use a query for that:
myRef.child(uid).orderByChild("name").equalToValue("test12").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot nodeSnapshot: dataSnapshot.getChildren()) {
nodeSnapshot.getRef().updateChildren(map);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException();
}
})
Update all children
This is a simpler version of the above, by removing the query condition:
myRef.child(uid).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot nodeSnapshot: dataSnapshot.getChildren()) {
nodeSnapshot.getRef().updateChildren(map);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException();
}
})

Firebase data retrieving issue in android studio

I want to retrieve data from firebase and display it on recycle view. I provided the correct path for data retrieving. But there is some problem i am unable to find it.
This code where i provided the child address.
final DatabaseReference nm= FirebaseDatabase.getInstance().getReference("Cart")
.child("Admin view")
.child(phoneNo)
.child("Products");
nm.addValueEventListener(new ValueEventListener()
{
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists())
{
for (DataSnapshot npsnapshot : dataSnapshot.getChildren())
{
cart l=npsnapshot.getValue(cart.class);
listData.add(l);
}
adapter = new cartAdapterr(listData, AdminShowOrderProductsActivity.this);
rv.setAdapter(adapter);
}
else
{
Toast.makeText(AdminShowOrderProductsActivity.this, "No Data for: " + phoneNo, Toast.LENGTH_SHORT).show();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
That is the screenshot of my firebase database and emulator. the phone number in toast message which is also present in firebase database. on node Phone number is correct but it shows error.
The way you work is correct, but you have a mistake, which is when the data is modified in Firebase, a new cartAdapterr is created and this operation is wrong.
You must first create an Adapter and then send the data.
for example you can create it onCreate and create a method inside the Adapter that receives List <Cart> as Shown below :
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
//..
adapter = new cartAdapterr(this);
loadDataFirebase():
}
void loadDataFirebase(){
final DatabaseReference nm= FirebaseDatabase.getInstance().getReference("Cart")
.child("Admin view")
.child(phoneNo)
.child("Products");
nm.addValueEventListener(new ValueEventListener()
{
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists())
{
for (DataSnapshot npsnapshot : dataSnapshot.getChildren())
{
cart l=npsnapshot.getValue(cart.class);
listData.add(l);
}
adapter.setDataList(listData);
}
else
{
Toast.makeText(AdminShowOrderProductsActivity.this, "No Data for: " + phoneNo, Toast.LENGTH_SHORT).show();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
In Adapter you have to create this setDataList (List<Cart> cartItems) :
public void setDataList (List<Cart> cartItems ) {
this.cartItems = cartItems;
notifyDataSetChanged();
}

Checking if a particular value exists in a particular place in the firebase database

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

Firebase get uid from email

I would like to get a uid from inputing an email for making it possible to add friends with an email.
Here is what I have gotten so far:
final DatabaseReference mRef = FirebaseDatabase.getInstance().getReference().child("users");
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
if (user != null) {
final String currentUserUid = user.getUid();
mRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.hasChild(uid)) {
DatabaseReference newRef = mRef.child(uid);
newRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (!dataSnapshot.hasChild(uid)) {
DatabaseReference database = FirebaseDatabase.getInstance().getReference();
String username = String.valueOf(dataSnapshot.child("username").getValue());
String email = String.valueOf(dataSnapshot.child("email").getValue());
String firebaseToken = String.valueOf(dataSnapshot.child("firebaseToken").getValue());
Friend friend = new Friend(uid, username, email, firebaseToken);
database.child(Constants.ARG_USERS)
.child(currentUserUid)
.child(Constants.ARG_FRIENDS)
.child(uid)
.setValue(friend)
.addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
mOnFriendDatabaseListener.onSuccess(context.getString(R.string.friend_successfully_added));
} else {
mOnFriendDatabaseListener.onFailure(context.getString(R.string.friend_unable_to_add));
}
}
});
} else {
Log.d("Adding Friend", "User already not exist");
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
} else {
Log.d("Adding Friend", "User does not exist");
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
This works if I input an uid directly but I would like to have my input be an email and get an uid out from it, or if there are other solutions please suggest.
This is how the database structure looks like:
Thanks for the help in advance.
To search for a user by their email address you need to order/filter on that property:
Query query = mRef.orderByChild("email").equalTo("example#example.com");
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
// There may be multiple users with the email address, so we need to loop over the matches
for (DataSnapshot userSnapshot: dataSnapshot.getChildren()) {
System.out.println(userSnapshot.getKey());
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
// Getting Post failed, log a message
Log.w(TAG, "find email address:onCancelled", databaseError.toException());
// ...
}
});
Not directly related to the question, but please restructure your data to remove the nesting of friends and profiles. For many reasons it's best to keep your Firebase data structure flat and separate user profiles from friends lists.
/users
uid1: ... profile for user 1
uid2: ... profile for user 2
/friends
uid1: ... friends list for user 1
uid2: ... friends list for user 2

how to use firebase query in if else condition

here is the code of the onclick of button , what i want to do is on click of his button app must fetch the email from the firebase database if successful it must show up in edit text that email found else show in Edit-text that email not found , here i am able to fetch the email and show that email found on Edit-text but not able to show the email not found (else part of the code ) instead i get this in console
W/PersistentConnection: pc_0 - Using an unspecified index. Consider adding '".indexOn": "email"' at /users/users to your security and Firebase rules for better performance
conbtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Firebase ref = new Firebase("https://(refrence of firebse database)");
final String searchEmail = emailcon.getText().toString().trim();
final Query query = ref.orderByChild("email").equalTo(searchEmail);
query.addValueEventListener(new ValueEventListener()
{
#Override
public void onDataChange(DataSnapshot dataSnapshot)
{
for (DataSnapshot child : dataSnapshot.getChildren())
{
final String fetchEmail;
Map<?, ?> value = (Map<?, ?>) child.getValue();
Log.d("main2activity ","User data : "+ value);
fetchEmail = (String) value.get("email");
Log.d("main2activity ","User email : "+ fetchEmail);
if (searchEmail.equals(fetchEmail))
{
emailcon.setText("email found hurray "+query.getRef());
}
else
{
emailcon.setText("still no email found!!");
}
}
}
#Override
public void onCancelled(FirebaseError firebaseError) {
}
});
}
});
Since you're firing a query, you will get a snapshot that can contain 0 or more children. If it contains any children, those children will have the email address you used in equalTo()
You need to handle the onDataChange() slightly differently:
query.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.hasChildren()) {
for (DataSnapshot child : dataSnapshot.getChildren()) {
emailcon.setText("email "+searchEmail+" found at URL "+child.getRef());
}
}
else {
emailcon.setText("still no email found!!");
}
}
#Override
public void onCancelled(FirebaseError firebaseError) {
}
});

Categories

Resources