I am using firebase database and need to create unique child node in database to start One to One chat. i am calling FireBaseDatabase.updateChildren(RoomName) to set single room for 2 user.
I am having issue in calling FireBaseDatabase.addListenerForSingleValueEvent(new ValueEventListener()
and under this Listener none of the method calls not even on public void onCancelled(DatabaseError databaseError)
Here is my code
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Snackbar.make(view, "Hello I am SnackBar", Snackbar.LENGTH_LONG).setAction("Action", null).show();
Log.d(TAG, "User Session Value " + userSession);
userSession = new UserSession(getActivity(), "Pref_FileName");
Log.d(TAG, "User Session Value After Init " + userSession);
final Map<String, Object> RoomName = new HashMap<>();
RoomTitle = userSession.getPhoneNO() + "-" + UserData.getPhone();
otherUserRoom = UserData.getPhone() + "-" + userSession.getPhoneNO();
Log.d(TAG, "Room Title Should Be " + RoomTitle);
DatabaseReference FireBaseDatabase = FirebaseDatabase.getInstance().getReference();
Log.d(TAG, "Chat room name from Database " + db.toString()); //GETTING THIS VALUE IN LOG
FireBaseDatabase.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.hasChild(RoomTitle)) {
intent2.putExtra("Get_Other",RoomTitle);
Log.d(TAG,"Room Exists No Need To Create It "+RoomTitle); // THIS LOG NEVER GENERATE
RoomNameFinal=RoomTitle;
}
else if (dataSnapshot.hasChild(otherUserRoom)){
intent2.putExtra("Get_Other",otherUserRoom);
Log.d(TAG,"Room Exists No Need To Create It "+otherUserRoom);// THIS LOG NEVER GENERATE
RoomNameFinal=otherUserRoom;
}
else {
Log.d(TAG,"None Of the above Room exist so Create one with RoomTitle "+RoomName);// THIS LOG NEVER GENERATE
intent2.putExtra("Get_Other",RoomTitle);
RoomName.put(RoomTitle, "");
FireBaseDatabase.updateChildren(RoomName);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.d(TAG,"On Cancelled Calling "+databaseError.getDetails()); // THIS LOG NEVER GENERATE
Log.d(TAG,"On Cancelled Calling "+databaseError.getMessage()); // THIS LOG NEVER GENERATE
Log.d(TAG,"On Cancelled Calling "+databaseError.toString()); // THIS LOG NEVER GENERATE
}
});
intent2.putExtra("Get_Phone", UserData.getPhone());
intent2.putExtra("Get_Image", UserData.getImage());
intent2.putExtra("Get_Name", UserData.getName());
Log.d(TAG,"Room Name Final "+RoomNameFinal);
startActivity(intent2);
}
});
Edit:Where i am adding child in my Firebase Database
You simply forget to indicate the name of your database reference in the function getReference().
For example, if you want to get the messages objects you need to set the DatabaseReference with something like
DatabaseReference myRef = database.getReference("message");
And the url of my database looks like :
https://myproject.firebaseio.com/message
This url is indicate on the top of the RealTimeDatabase tab in your Firebase dashboard.
Hope this help.
I solved by make some edit in code.I am not sure why this is happened but for some who still stuck at this issue, will get little help from this. Instead of calling FireBaseDatabase.updateChildren(RoomName) from directly in onDataChange i create a method which will be called from onDataChange
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Snackbar.make(view, "Hello I am SnackBar", Snackbar.LENGTH_LONG).setAction("Action", null).show();
Log.d(TAG, "User Session Value " + userSession);
userSession = new UserSession(getActivity(), "Pref_File");
RoomName = new HashMap<>();
RoomTitle = userSession.getPhoneNO() + "-" + UserData.getPhone();
otherUserRoom = UserData.getPhone() + "-" + userSession.getPhoneNO();
Log.d(TAG, "Room Title Should Be " + RoomTitle);
DatabaseReference db = FirebaseDatabase.getInstance().getReference();
Log.d(TAG, "Chat room name from Database " + db.toString());
db.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Log.d(TAG,"On Data Change Calling "+dataSnapshot);
if (dataSnapshot.hasChild(RoomTitle)) {
Log.d(TAG,"Room Exists No Need To Create It 1"+RoomTitle);
RoomName(RoomTitle,false);
}
else if (dataSnapshot.hasChild(otherUserRoom)){
Log.d(TAG,"Room Exists No Need To Create It 2 "+otherUserRoom);
RoomName(otherUserRoom,false);
}
else {
Log.d(TAG,"None Of the above Room exist so Create one with RoomTitle "+RoomName);
RoomName(RoomTitle,true);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.d(TAG,"On Cancelled Calling "+databaseError.getDetails());
Log.d(TAG,"On Cancelled Calling "+databaseError.getMessage());
Log.d(TAG,"On Cancelled Calling "+databaseError.toString());
}
});
This method i created to call FireBaseDatabase.updateChildren(RoomName) which is not calling from If Else Statement of my previous code.
public void RoomName (String Name,boolean RoomExist){
if (RoomExist){
Log.d(TAG,"Room Not Exist Creating One in METHOD NAME ROOM NAME "+RoomExist);
RoomName.put(Name, "");
FireBaseDatabase.updateChildren(RoomName);
}
Log.d(TAG,"Method ROOM NAME CALLING Value Of ROOM NAME FINAL "+Name);
intent = new Intent(getActivity(), Chat_Screen.class);
intent.putExtra("Get_Phone", UserData.getPhone());
intent.putExtra("Get_Image", UserData.getImage());
intent.putExtra("Get_Name", UserData.getName());
intent.putExtra("Get_Other",Name);
startActivity(intent);
}
Now my onDataChange call as i want.I hope it will someone who has same kind of issue.
Related
When I read a Firebase database, the city and town variables show me to as null. Why?
Denemesiralamaisyerleri deneme = new Denemesiralamaisyerleri();
FirebaseUser firebaseUser = firebaseAuth.getCurrentUser();
String id = firebaseUser.getUid();
DatabaseReference userdata = FirebaseDatabase.getInstance().getReference().child("users").child(id);
ValueEventListener rdn = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) { // Read user info from the database
deneme = dataSnapshot.getValue(Denemesiralamaisyerleri.class);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Toast.makeText(UserInterfaceBerber.this, databaseError.getMessage(), Toast.LENGTH_LONG).show();
}
};
userdata.addValueEventListener(rdn);
city = deneme.getCity();
town = deneme.getTown();
ilin.setText(city);
ilcenin.setText(town);
Toast.makeText(UserInterfaceBerber.this, city + " " + town + " ", Toast.LENGTH_LONG).show();
My database structure like this:
users
igORGoET3gT6i8CV4wvtuN3l08z1
city:
"Antalya"
email:
"ahmetbulur#gmail.com"
namesurname:
"Ahmet bulur"
phonenum:
"05346789445"
town:
"Alanya"
Also, for this toast message, the "city" and "town" variable show as null. I expect that it shows me "Antalya" + "Alanya" for the toast message:
Toast.makeText(UserInterfaceBerber.this, city + " " + town + " ", Toast.LENGTH_LONG).show();
Because the data is loaded from Firebase asynchronous, you should use that data only when the operation completes, and this only inside the onDataChange() method, like in the following lines of code:
Denemesiralamaisyerleri deneme=new Denemesiralamaisyerleri();
FirebaseUser firebaseUser=firebaseAuth.getCurrentUser();
String id=firebaseUser.getUid();
DatabaseReference userdata=FirebaseDatabase.getInstance().getReference().child("users").child(id);
ValueEventListener rdn=new ValueEventListener() {
#Override
public void onDataChange( DataSnapshot dataSnapshot) { //read user info from database
deneme=dataSnapshot.getValue(Denemesiralamaisyerleri.class);
city=deneme.getCity();
town=deneme.getTown();
ilin.setText(city);
ilcenin.setText(town);
Toast.makeText(UserInterfaceBerber.this,city+" "+town+" ",Toast.LENGTH_LONG).show();
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Toast.makeText(UserInterfaceBerber.this,databaseError.getMessage(),Toast.LENGTH_LONG).show();
}
};
userdata.addValueEventListener(rdn);
For more info, I recommend you see the last part of my answer from this post in which I have explained how it can be done using a custom callback. You can also take a look at this video for a better understanding.
I tried to read data from firebase db and return values to another method.To do that I added interface and use it as a callback function and tried to wait until data filled. But it still give the null pointer exception.
private interface FirebaseCallback {
void onCallBack(Card card);
}
// method to read travel Cards
public void readCard(final FirebaseCallback fb) {
cardNo = (EditText)findViewById(R.id.editTextCardNo);
ValueEventListener cardListner = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(dataSnapshot.exists()) {
travelCard = dataSnapshot.getValue(Card.class);
fb.onCallBack(travelCard);
}
else displayMessage(inValidTravelCard);
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.d("ERROR : ", databaseError.getMessage());
}
};
String cn = cardNo.getText().toString();
Query q = FirebaseDatabase.getInstance().getReference("Card").orderByChild("cardNumber").equalTo(cn).limitToFirst(1);
q.addListenerForSingleValueEvent(cardListner);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_card_reader);
System.out.println("fffffffffffffffffffffffffffffff " + " BEFORE>..........................");
readCard(new FirebaseCallback() {
#Override
public void onCallBack(Card card) {
Log.d("card = ",card.getAccountId());
}
});
System.out.println("fffffffffffffffffffffffffffffff " + " After>..........................");
}
});
}
Here's the ERROR :
Here's the database
If you parse the stack trace you get the error message you get is println needs a message, triggered from Log.d. In the code you shared, there are two statements that could trigger that message:
Log.d("ERROR : ", databaseError.getMessage());
And
Log.d("card = ",card.getAccountId());
It seems quite unlikely that databaseError.getMessage() returns nothing, so it's more likely that card.getAccountId() returns nothing or null. A simple solution is to check for that:
Log.d("card = ", card.getAccountId() != null ? card.getAccountId() : "No account ID found on card");
Null pointer exceptions are extremely common, and knowing how to troubleshoot them is a skill that will serve you well. I recommend studying: What is a NullPointerException, and how do I fix it?.
I have a Registration form (username, password, phone number) and a submit button. I want to check if this username has been registered before. If it is not then create user with credentials in the form.
DB structure
- users
--- -L3HQjgyXe6iNC0r0Ftr
------ mobile: "+15553334444"
------ password: "yoyo"
------ uid: "-L3HQjgyXe6iNC0r0Ftr"
------ username: "myusername"
When I check against a username that exists, i get the correct Toast. However, if the username being checked does not exist, it does not run the code in the else statement under the Toast. Any suggestions?
btnSubmit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final String username = txtUsername.getText().toString();
final String password = txtPassword.getText().toString();
final String number = txtNumber.getText().toString();
final boolean[] createUser = new boolean[1];
user = SerializableHelper.loadDataFromFile(OnBoardingActivity.this);
if (user != null) {
Log.d(TAG, "User uid: " + user.getUid());
Log.d(TAG, "User username: " + user.getUsername());
Toast.makeText(OnBoardingActivity.this, "You're already Registered!", Toast.LENGTH_SHORT).show();
} else {
Query query = mFBUsers.orderByChild("username").equalTo(username);
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot child : dataSnapshot.getChildren()) {
if (child.getValue(User.class).getUsername().equals(username)) {
Toast.makeText(OnBoardingActivity.this, "username already exists!", Toast.LENGTH_SHORT).show();
} else {
Log.d(TAG, "TELL APP TO CREATE NEW USER");
String tempUid = mFBUsers.push().getKey();
user = new User(tempUid, username, password, number);
// save user data locally before pushing to Firebase
SerializableHelper.saveSerializable(OnBoardingActivity.this, user);
mFBUsers.child(tempUid).setValue(user);
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
}
});
One vey obvious problem in your code is that you are updating the createUser[0] inside the onDataChange method of ValueEventListener but you are using it outside it.
Do note that ValueEventListener is executed asynchronously. So it will proceed with execution of the remaining code without waiting for onDataChange to be called.
So if you want to wait for the updated value of createUser[0], you should call the entire if block of code from inside the onDataChange
Hope this helps. Let me know if you want me to elaborate further.
OK, I figured out what my problem code was
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot child : dataSnapshot.getChildren()) {
if (child.getValue(User.class).getUsername().equals(username)) {
Toast.makeText(OnBoardingActivity.this, "username already exists!", Toast.LENGTH_SHORT).show();
return;
}
}
Log.d(TAG, "TELL APP TO CREATE NEW USER");
String tempUid = mFBUsers.push().getKey();
user = new User(tempUid, username, password, number);
// save user data locally before pushing to Firebase
SerializableHelper.saveDataToFile(OnBoardingActivity.this, user);
mFBUsers.child(tempUid).setValue(user);
}
I am creating an application that starts the home activity and creates the methods in the Firebase database. This does it correctly but each user has a variable called acoins and I want this every time someone enters if it already exists that is not set to 0 that stays with the value that has.
This is the code I have :
databaseRef.child("users/" + user.getDisplayName() + "/acoins").setValue(0);
private void setUserData(FirebaseUser user) {
nameTextView.setText(user.getDisplayName());
emailTextView.setText(user.getEmail());
idTextView.setText(user.getUid());
Glide.with(this).load(user.getPhotoUrl()).into(photoImageView);
DatabaseReference databaseRef = FirebaseDatabase.getInstance().getReference();
databaseRef.child("users/" + user.getDisplayName()).setValue(user.getEmail());
databaseRef.child("users/" + user.getDisplayName() + "/acoins").setValue(0);
}
Try this in setUserData() method
DatabaseReference databaseRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference dr = ref.child("users").child(user.getDisplayName).child("acoins");
dr.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Long acoins1 = (Long)dataSnapshot.getValue();
if(acoins1 != 0)
{//create toast or anything here
}
else{
databaseRef.child("users/" + user.getDisplayName() + "/acoins").setValue(0);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
I am implementing an application using FireBase, in this application I have to save user information with user enter unique id. How can I do that. Actually it saving the data with random generated value. But I want to add a user enter unique id.
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
txtDetails = (TextView) findViewById(R.id.txt_user);
inputName = (EditText) findViewById(R.id.name);
inputEmail = (EditText) findViewById(R.id.email);
btnSave = (Button) findViewById(R.id.btn_save);
mFirebaseInstance = FirebaseDatabase.getInstance();
// get reference to 'users' node
mFirebaseDatabase = mFirebaseInstance.getReference("users");
// store app title to 'app_title' node
mFirebaseInstance.getReference("app_title").setValue("Realtime Database");
// app_title change listener
mFirebaseInstance.getReference("app_title").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Log.e(TAG, "App title updated");
// update toolbar title
}
#Override
public void onCancelled(DatabaseError error) {
// Failed to read value
Log.e(TAG, "Failed to read app title value.", error.toException());
}
});
// Save / update the user
btnSave.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String name = inputName.getText().toString();
String email = inputEmail.getText().toString();
// Check for already existed userId
if (TextUtils.isEmpty(userId)) {
createUser(name, email);
} else {
createUser(name, email);
}
}
});
toggleButton();
}
// Changing button text
private void toggleButton() {
if (TextUtils.isEmpty(userId)) {
btnSave.setText("Save");
} else {
btnSave.setText("Save");
}
}
/**
* Creating new user node under 'users'
*/
private void createUser(String name, String email) {
// TODO
// In real apps this userId should be fetched
// by implementing firebase auth
if (TextUtils.isEmpty(userId)) {
userId = mFirebaseDatabase.push().getKey();
}
User user = new User(name, email);
mFirebaseDatabase.child(userId).push().setValue(user);
addUserChangeListener();
}
/**
* User data change listener
*/
private void addUserChangeListener() {
// User data change listener
mFirebaseDatabase.child(userId).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
User user = dataSnapshot.getValue(User.class);
// Check for null
if (user == null) {
Log.e(TAG, "User data is null!");
return;
}
Log.e(TAG, "User data is changed!" + user.name + ", " + user.email);
// Display newly updated name and email
// txtDetails.setText(user.name + ", " + user.email);
// clear edit text
inputEmail.setText("");
inputName.setText("");
toggleButton();
}
#Override
public void onCancelled(DatabaseError error) {
// Failed to read value
Log.e(TAG, "Failed to read user", error.toException());
}
});
}
private void updateUser(String name, String email) {
// updating the user via child nodes
if (!TextUtils.isEmpty(name))
mFirebaseDatabase.child(userId).child("name").setValue(name);
if (!TextUtils.isEmpty(email))
mFirebaseDatabase.child(userId).child("email").setValue(email);
}
To save user data under an unique identifier i suggest you using the email address in stead of pushing a new key or using the uid. The email address is unique and easy to use. But because Firebase does not accept . symbol in the key i suggest you encode the email address like this:
name#email.com -> name#email,com
As you see, i have changed the the dot symbol . with a coma ,. To achive this i recomand you using this methods:
static String encodeUserEmail(String userEmail) {
return userEmail.replace(".", ",");
}
static String decodeUserEmail(String userEmail) {
return userEmail.replace(",", ".");
}
Hope it helps.