so basically my problem is kind of weird. It updates the values however, I need to close the app again in order for me to update the fields again.
Here is my update code.
saveEditProfile_studentbtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
FirebaseAuth firebaseAuth = FirebaseAuth.getInstance();
String studentUser = firebaseAuth.getCurrentUser().getUid();
final DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference("Users").child(studentUser);
Toast.makeText(StudentProfileEditAct.this, studentUser, Toast.LENGTH_SHORT).show();
databaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
String replaceName = studentChangeFullName.getText().toString().trim();
String replacePhoneNumber = studentChangePhoneNum.getText().toString().trim();
Map<String, Object> updates = new HashMap<>();
updates.put("fullName", replaceName);
updates.put("phoneNumber", replacePhoneNumber);
databaseReference.updateChildren(updates);
Toast.makeText(StudentProfileEditAct.this, "Changes has been made", Toast.LENGTH_SHORT).show();
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
}
});
and here's my realtime database. I just want to change the name and the phone number.
But for some strange reason, it logout the current user and relog it back and when i'll try to update the values, the values from the realtime (fullname,phonenumber) the data goes back from the old value and new value and it's highlighted as yellow.
The images below when I tried to update the second time around without closing the app first.
If you want to update a value in the database based on its current value, you should use a transaction to prevent conflicting writes.
But in your code, I see no reason to first read the user node before updating it. You can use this much simpler code, which may solve your problem:
public void onClick(View v) {
FirebaseAuth firebaseAuth = FirebaseAuth.getInstance();
String studentUser = firebaseAuth.getCurrentUser().getUid();
final DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference("Users").child(studentUser);
String replaceName = studentChangeFullName.getText().toString().trim();
String replacePhoneNumber = studentChangePhoneNum.getText().toString().trim();
Map<String, Object> updates = new HashMap<>();
updates.put("fullName", replaceName);
updates.put("phoneNumber", replacePhoneNumber);
databaseReference.updateChildren(updates);
Toast.makeText(StudentProfileEditAct.this, "Changes has been made", Toast.LENGTH_SHORT).show();
}
One quick fix is to use the .setValue property in the Database Reference.
You may use a model class if you intended to change different fields at once.
Based on firebase documentation, valueeventlisteners are generally made for reading and listening to data changes and not writing which might be the problem of your code
Related
I am new to Java, Android, and Firebase. What I am trying to do here is read what's already uploaded to firebase, but the code doesn't work. I put a breakpoint and found that it doesn't even run the listener. What is the problem here? Any help is much appreciated.
Here is my database on Firebase:
This is the code I used to retrieve the information from the database.
//in Main Activity
DatabaseReference mDatabase = FirebaseDatabase.getInstance().getReference();
//Rest of the code is within onCreate()
mDatabase.child("9099").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String number = dataSnapshot.child("Number").getValue().toString();
String time = dataSnapshot.child("Time").getValue().toString();
String chan1 = dataSnapshot.child("Channel1").getValue().toString();
String chan2 = dataSnapshot.child("Channel2").getValue().toString();
testing.setText(String.format(time));
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
First of all, I hope anyone could help adjust my code line using document reference as below.
As you can see from my firebase console below, my FaceEmotion-id document has Faceemotion and Timestamp field.
Using my codes below, everytime user gets different emotion, the firestore will overwrite the emotions. Hence I couldnt see what are the different emotions user get when using my app and the different time he/she has used my app.
I need to prevent overwriting for the two fields mentioned above. Please help me. What I want is to add fields in the document not overwriting it.
One more, I have no idea how to generate different id for the document named FaceEmotion-id. I actually had referenced the document beforehand using Uid as you can see from my code below. But for the subdocument in the "Result" collection. I cant seem to find a way to make it unique.
This is my codes:
public static final String TAG = "TAG";
FirebaseAuth fAuth;
FirebaseFirestore fStore;
String userID;
String FaceEmotion;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detection);
fAuth = FirebaseAuth.getInstance();
fStore = FirebaseFirestore.getInstance();
StartQues = (Button) findViewById(R.id.view_question);
StartQues.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String Emotion = EmotionType.toString();
userID = fAuth.getCurrentUser().getUid();
FaceEmotion = "FaceEmotion";
DocumentReference documentReference = fStore.collection("users").document(userID).collection("Result").document("FaceEmotion-id");
//DocumentReference documentReference = fStore.collection("users").document(userID).collection("FaceEmotion").document(Emotion);
Map<String,Object> user = new HashMap<>();
user.put("FaceEmotion",Emotion);
user.put("timestamp", FieldValue.serverTimestamp());
documentReference.set(user).addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
Log.d(TAG, "onSuccess: Data has been saved "+ userID);
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.d(TAG, "onFailure: " + e.toString());
}
});
It sounds like you want to store a list of timestamps and emojis. If you want to store those in a single document, the logical data structure would be to store them in an array/set with something like this:
user.put("FaceEmotion",Emotion);
user.put("timestamp", FieldValue.serverTimestamp());
documentReference.update("emotions", FieldValue.arrayUnion(user))
Every time this code runs, it will add a new item to the emotions array in the document.
Also see the Firebase documentation on updating elements in an array.
I have the following data structure in my firebase. I am implementing a coupon based system where you enter a code in dialogue box and it is searched across the database. So I have been trying to figure out this but I haven't found the perfect query that can search the code, if found, then get all the other child values too.
Below is the code that i have been trying with:
private void couponsearch() {
final EditText taskEditText = new EditText(this);
AlertDialog.Builder dialog = new AlertDialog.Builder(this)
.setTitle("Akiba Yangu")
.setMessage("Enter Akiba Code Here.")
.setIcon(R.drawable.akyi)
.setView(taskEditText).setPositiveButton("SAVE",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int id) {
String stringe = taskEditText.getText().toString();
DatabaseReference mDatabase = FirebaseDatabase.getInstance().getReference();
mDatabase.child("codes").orderByChild("code").equalTo(stringe).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Coupons coo = dataSnapshot.getValue(Coupons.class);
String name = dataSnapshot.getKey();
int codez = coo.getValuee();
code.setText(name);
if(dataSnapshot != null && dataSnapshot.getChildren().iterator().hasNext()){
for(DataSnapshot ds : dataSnapshot.getChildren()) {
codegotten();
}
}else {
nocode();
}
int val = coo.getValuee();
Akibasavings as = new Akibasavings();
String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
System.out.println(val);
code.setText(name);
as.setName(name);
as.setAmount(val);
final Firebase ref = new Firebase("https://akiba-c9600.firebaseio.com/");
Firebase newRef = ref.child("Savings"+uid).push();
newRef.setValue(as);
sendNotification();
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
public void onCancelled(FirebaseError firebaseError) {
//Username Does Not Exist
}
});
}
});
dialog.show();
}
I would like to search the code, check if it is really there or not: if it is there I need to get all the other values too, i.e there are three nodes in every child. code, brand, value. After I have checked that the code exists, I would like to also get the other values associated with it. Regards
To achieve this, i recomand you change the structure of your database a little bit by adding a new node named coupons. Your database should look like this:
Firebase-root
--- coupons
TTUUPP: true
KKLLOO: true
To check if a coupon exists in your database, just add a listener on the new created node and use exists() method. This is a coomon practice within Firebase named denormalization and is for simplify and reduce query and bandwith. This what you need.
What you need is Query.
DatabaseReference mDatabase = FirebaseDatabase.getInstance().getReference();
Query mQuery = mDatabase.child("codes").orderByChild("code").equalTo(stringe);
mQuery.addListenerForSingleValueEvent(new ValueEventListener() {
// use single value event listener to detach listener immediately after query
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.getValue() != null) {
// code exists, cast your data to relevant object
// note that if multiple entries exists, you need to loop through them
} else {
// code does not exists
}
}
});
Read the official document here.
Note that you must remember to index your firebase properly! Query on firebase is not the same as local database query. If you do not index your firebase, the query will download everything under the codes section into user phone, before doing the search locally on user phone. This will consume high bandwidth and memory. Learn more about index here. Read about my personal issue with index previously here.
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.
Your onDataChange() needs to handle the fact that the snapshot contains a list of result by looping over DataSnapshot.getChildren():
mDatabase.child("codes").orderByChild("code").equalTo(stringe).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot childSnapshot: dataSnapshot.getChildren()) {
Coupons coo = childSnapshot.getValue(Coupons.class);
String name = childSnapshot.getKey();
int codez = coo.getValuee();
code.setText(name);
...
}
}
String userID = user.getUid();
mFirebaseDatabase = FirebaseDatabase.getInstance();
I have userId of the user so when I'm opening my app for the 2nd time(after signing in) I should not show the select user type layout. So I ve to check whether the use is Customer or Staff internally. So the problem is I ve to check the User Id is there . I couldn't find any method to get whether user Id is there or not! There is method called addListenerForSingleValueEvent but that won't help me in my scenario. Pic of the database is given here
I don't know how to continue after this
mFirebaseDatabase.getReference().child("Users").child("Customers")
To check if an user exists in a particular section of your Firebase database, first you need to add a listener and then use exists() method directly on the dataSnapshot object. So, asumming that Users node is a direct child of the Firebase-database root, please use the following code:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference customersRef = rootRef.child("Users").child("Customers").child(userID);
ValueEventListener eventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(dataSnapshot.exists()) {
//do somethig
} else {
//do something else
}
}
#Override
public void onCancelled(DatabaseError databaseError) {}
};
customersRef.addListenerForSingleValueEvent(eventListener);
I'm building an app that is basically a table for soccer that updates every time I change it in my DB.
I'm using Firebase in this way:
I'm trying to use an addValueEventListener, but I don't know which one of the values is the one that changes (dif,score,points...) therefore I don't which field in my table I should update.
public class table extends AppCompatActivity {
Button insert;
TextView name, games, win, lost, tie, score, dif, points;
Team A;
DatabaseReference mRootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference FootballRef = mRootRef.child("Football");
DatabaseReference HouseARef = FootballRef.child("HouseA");
protected void onStart() {
super.onStart();
ValueEventListener postListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
// Get Post object and use the values to update the UI
String key = dataSnapshot.getKey() ;
Toast.makeText(table.this,key, Toast.LENGTH_SHORT).show();
// ...
}
#Override
public void onCancelled(DatabaseError databaseError) {
// Getting Post failed, log a message
// ...
}
};
HouseARef.addValueEventListener(postListener);
}
}
See here, when let's say I'm updating the name of housaA, I want to get back the key that got updated (in my case, name), but when I'm using
dataSnapshot.getKey() the Toast I'm getting back is HouseA and not name.
You won't be able to do this using a valuelistener.
Instead put a childeventlistener on the houseA.
Now inside onChildChanged, you should get the child node under houseA which has changed as a datasnapshot and from this snapshot, you can get the key which has changed