I've traced my code to the root cause of my crashes and apparently this constructor is unable to update the variables of the class. I am getting null pointer exception when I'm trying to get data from this class. You can safely assume that the record is already in the database and all it has to do is just get the data and place it in the class/object. I simply want to get the name for now because I'm testing if the object is still null or not.
class Saver{
private String name;
// constructor of Saver class
public Saver(final String uid) {
Log.d("Saver.java","Reached here"); // this works
FirebaseDatabase.getInstance().getReference().addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(final DataSnapshot dataSnapshot) {
Log.d("Saver.java", "OnDataChange"); // does not work
if(dataSnapshot.hasChild("users/" + uid)){
LoadRecord(dataSnapshot, uid);
}
else{
// set a new record into the database
FirebaseDatabase.getInstance().getReference().child("users/" + uid).setValue(CreateNewRecord(FirebaseAuth.getInstance().getCurrentUser())).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if(task.isSuccessful()){
LoadRecord(dataSnapshot, uid);
}
else{
Log.e("Saver.java","Failed to set record in database");
}
}
});
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.e("LifeSaver.java","Error: " + databaseError.getMessage());
}
});
}
// This function loads the data into the object
private void LoadRecord(DataSnapshot dataSnapshot, String uid){
Log.d("LifeSaver.java","Uid:"+uid);
// load the existing record in the database
Saver temp = dataSnapshot.child("users/" + uid).getValue(Saver.class);
setName(temp.getName());
}
}
public void setName(String name) {
this.name = name;
}
private Saver CreateNewRecord(FirebaseUser firebaseUser){
Saver saver = new Saver ();
saver.setName(firebaseUser.getDisplayName());
Log.d("saver","saver name: " + saver.getName());
return continuLifeUser;
}
Obviously the function onDataChange will not run until something changed on the database.
How can I manually trigger this function, if possible?
Should I have a DataSnapshot that has the children of this node? If so, how? (show code please so I can visualize what you are explaning)
Is there a better way of doing this?
Edit 1:
Here's the logcat statements from the constructor that should have called the FirebaseDatabase:
D/Saver.java: Reached here with hA4hZrBieISwMOZaMYe7m6K5tpI3
I/DynamiteModule: Considering local module com.google.android.gms.firebase_database:4 and remote module com.google.android.gms.firebase_database:6
I/DynamiteModule: Selected remote version of com.google.android.gms.firebase_database, version >= 6
I/art: DexFile_isDexOptNeeded failed to open oat file '/data/dalvik-cache/x86_64/data#data#com.google.android.gms#app_chimera#m#00000004#DynamiteModulesC_GmsCore_prodlmp_alldpi_release.apk#classes.dex' for file location '/data/data/com.google.android.gms/app_chimera/m/00000004/DynamiteModulesC_GmsCore_prodlmp_alldpi_release.apk': Failed to open oat filename for reading: No such file or directory
D/Saver.java: Ended here
D/LoginAct.java: Name: null
For getting all the names from all users under users node, please use the following code:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference usersRef = rootRef.child("users");
ValueEventListener eventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot ds : dataSnapshot.getChildren()) {
String name = ds.child("name").getValue(String.class);
Log.d("TAG", name);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {}
};
usersRef.addListenerForSingleValueEvent(eventListener);
The output will be:
Michael Ong
//other names
If you want to get only the name of a particular user, please use the following code:
FirebaseUser firebaseUser = firebaseAuth.getCurrentUser();
String uid = firebaseUser.getUid();
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference uidRef = rootRef.child("users").child(uid);
ValueEventListener eventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String name = dataSnapshot.child("name").getValue(String.class);
Log.d("TAG", name);
}
#Override
public void onCancelled(DatabaseError databaseError) {}
};
uidRef.addListenerForSingleValueEvent(eventListener);
The output will be only a single record:
Michael Ong
I resolved the problem by having a loading screen. I should have remembered that the call was Async and that it needed a receiver to call the function that will place the data before moving on to the next activity.
private interface OnGetDataListener {
void onSuccess(DataSnapshot dataSnapshot);
void onFailure();
}
Here's a small code for the listener that you'll have to implement when you're calling the database to get the data. You can check for other posts similar to this one.
Hi first you should add data to database , then only it will work . Looks like there is no data available in Firebase.Just add a key value pair in firebase database , then it will be triggered.
FirebaseDatabase.getInstance().getReference().child("users/" + uid).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(final DataSnapshot dataSnapshot) {
Log.d("Saver.java", "OnDataChange"); // does not work
if(dataSnapshot!=null){
LoadRecord(dataSnapshot);
}
else{
// set a new record into the database
FirebaseDatabase.getInstance().getReference().child("users/" + uid).setValue(CreateNewRecord(FirebaseAuth.getInstance().getCurrentUser())).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if(task.isSuccessful()){
LoadRecord(dataSnapshot);
}
else{
Log.e("Saver.java","Failed to set record in database");
}
}
});
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.e("LifeSaver.java","Error: " + databaseError.getMessage());
}
});
}
// Load record should be like this...
private void LoadRecord(DataSnapshot dataSnapshot){
Log.d("LifeSaver.java","Uid:"+uid);
// load the existing record in the database
Saver temp = dataSnapshot.getValue(Saver.class);
setName(temp.getName());
}
}
Related
I'm making a game, if the player wins, then the victory is added to the database. How can I read the data from here?
and paste here:
I read the player's name in a different way, which cannot be repeated with victories and defeats.
To be able to read the data under the jjjj node, please use the following lines of code:
DatabaseReference db = FirebaseDatabase.getInstance().getReference();
DatabaseReference nameRef = db.child("players").child("jjjj");
nameRef.get().addOnCompleteListener(new OnCompleteListener<DataSnapshot>() {
#Override
public void onComplete(#NonNull Task<DataSnapshot> task) {
if (task.isSuccessful()) {
DataSnapshot snapshot = task.getResult();
String loses = snapshot.child("loses").getValue(Long.class);
String name = snapshot.child("name").getValue(String.class);
String wins = snapshot.child("wins").getValue(Long.class);
Log.d("TAG", loses + "/" + name + "/" + wins);
} else {
Log.d("TAG", task.getException().getMessage()); //Never ignore potential errors!
}
}
});
The result in the logcat will be:
3/jjjj/4
Things to notice:
Always create a reference that points to the node that you want to read.
If your database is located in another lcoation than the default, check this answer out.
use this method
This is the method of fetching data from the firebase realtime database
DatabaseReference reference = FirebaseDatabase.getInstance().getReference();
reference.child("players").child(name).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
for (DataSnapshot dataSnapshot : snapshot.getChildren()){
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
I need to retrieve specific info from Firebase Realtime Database to send push messages, but don't know how to do it, I need to get in String the device token from all the users, so tried to call Users, the should call user ids (this part is where I'm lost, don't know how to get this path), and then device token.
This is what I have :
UsersRef = FirebaseDatabase.getInstance().getReference().child("Users");
usersIDs = UsersRef.getKey().toString();
UsersRef.child(usersIDs).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NotNull DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
if (dataSnapshot.hasChild("device_token")) {
receiverUserDeviceToken = dataSnapshot.child("device_token").getValue().toString();
}
}
}
#Override
public void onCancelled(#NotNull DatabaseError error) {
}
});
According to your last comment:
Correct, I need to get both values.
Please use the following lines of code:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference users = rootRef.child("Users");
usersRef.get().addOnCompleteListener(new OnCompleteListener<DataSnapshot>() {
#Override
public void onComplete(#NonNull Task<DataSnapshot> task) {
if (task.isSuccessful()) {
for (DataSnapshot userSnapshot : task.getResult().getChildren()) {
String deviceToken = userSnapshot.child("device_token").getValue(String.class);
Log.d("TAG", deviceToken);
}
} else {
Log.d("TAG", task.getException().getMessage()); //Don't ignore potential errors!
}
}
});
The result in the logcat will be:
f4...XMY:APA...wr3
eff...8NT:APA...Bd7
Remember, to be able to get all the results from a DataSnapshot object, you have to iterate through the children using .getChildren().
the databas
setContentView(R.layout.activity_main);
Button readBtn = (Button) findViewById(R.id.readBtn);
EditText testInputTxt = (EditText) findViewById(R.id.testInputTxt);
rootRef = FirebaseDatabase.getInstance().getReference().child("Login");
Query query = rootRef.orderByChild("LoginUserName").equalTo(testInputTxt.getText().toString());
readBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
String passwordUser = snapshot.child("LoginPassword").getValue(String.class);
testInputTxt.setText(passwordUser+"tatata");
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
}
});
the query works fine it detects that the user is existexists but i wanted to retrieve the value of LoginPassword but it returns null i tried the for DataBase....:snapshot code but it won't detect
Since you are using a Query object, it means that you can potentially get multiple results from the database. That being said, you have to loop through the results using a call to .getChildren() as seen in the following lines of code:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference loginRef = rootRef.child("Login");
Query query = loginRef.orderByChild("LoginUserName").equalTo(testInputTxt.getText().toString());
query.get().addOnCompleteListener(new OnCompleteListener<DataSnapshot>() {
#Override
public void onComplete(#NonNull Task<DataSnapshot> task) {
if (task.isSuccessful()) {
for (DataSnapshot ds : task.getResult().getChildren()) {
String passwordUser = ds.child("LoginPassword").getValue(String.class);
testInputTxt.setText(passwordUser+"tatata");
}
} else {
Log.d("TAG", task.getException().getMessage()); //Don't ignore potential errors!
}
}
});
Please also note that if two users have the same "LoginUserName", then your TextView will always display the value of the last one. So always be sure to have unique user names. To check if a user name already exists, please check my answer from the following post:
Checking if a particular value exists in the Firebase database
I need to get nickname value from Firebase Real time database after button is clicked. So i made singleValueListner() in button´s onClick method. But it don´t work.
I have tried debug it, but code didn´t get into singleValueEventListener()
Button getName = (Button)findViewById(R.id.getName);
getName.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
DatabaseReference db = FirebaseDatabase.getInstance().getReference().child("Member").child(user.getUid());
db.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot data : dataSnapshot.getChildren()) {
TextView tv = (TextView)findViewById(R.id.tv);
tv.setText(data.child("nickname").getValue().toString());
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
});
Database JSON structure:
{
"Member" : {
"1Zuv6VZZ0kPluwc33f1QQQ7DZD93" /* UID */ : {
"-LgIHwiAjfuh5pjK7wzl" : {
"actualScore" : 0,
"bestScore" : 0,
"email" : "some#email.com",
"nickname" : "Vitek",
"season" : 0
}
}
}
}
Database structure:
https://drive.google.com/file/d/15B4b6Rb_WAiS6fioI9gItyijrbDiVjzJ/view
I need to get nickname, I think this is writen good, but not. So, what is wrong?
To get the value of your nickname property, please use the following lines of code:
String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference uidRef = rootRef.child("Member").child(uid);
ValueEventListener valueEventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String nickname = dataSnapshot.child("nickname").getValue(String.class);
Log.d(TAG, nickname);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Log.d(TAG, databaseError.getMessage()); //Don't ignore errors!
}
};
uidRef.addListenerForSingleValueEvent(valueEventListener);
The output in your logcat will be:
Vitek
So there is no need to loop through the DataSnapshot object in order to get the value of your nickname property. If you don't get this result, please check the logcat to see if you have an error message printed out.
You are only referring up to user's id but there is also a parent key of user detail which you need to reference.
tv.setText(data.child("LgiH------").child("nickname").getValue().toString());
but try to remove that second key from your registering user's code because it is not helpful.
You have made a mistake in refering your firebase root node. just change your line as below :
DatabaseReference db = FirebaseDatabase.getInstance().getReference("Member");
Now,just call your singlevalue event.
db.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot data : dataSnapshot.getChildren()) {
TextView tv = (TextView)findViewById(R.id.tv);
tv.setText(data.child("nickname").getValue().toString());
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
This will do your stuff. try debugging your code with log at step by step.
I need to check if conversation child is exist.
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference().child("users").child(senderId);
rootRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
if (snapshot.hasChild("conversations")) {
if (snapshot.child("conversations").hasChild(receiverId)) {
ConversationLocationModel conversationModel = snapshot.child("conversations").child(receiverId).getValue(ConversationLocationModel.class);
roomId = conversationModel.getLocation();
getAllMessage();
} else {
addinLocation();
}
} else {
addinLocation();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {}
});
Currently I am using above code to check if child has exist i do not want to check every time so how it can be possible if there is any child exist is there any query for checking child existence.
If you want to check if any child exists, then you can do this:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference().child("users").child(senderId).child("conversations");
rootRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
if (snapshot.exists()){
//checks if this snapshots exists
}else{
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
You can change it depending on your database. But the above will check child("users").child(senderId).child("conversations") if conversations exists then it will enter it and see all its children.