How to be sure that setValue to firebase child worked successfully? - android

I am using addOnCompleteListener, but I need to setValue to more than one child at time, it will not be good if I check if 1st child updated then update the 2nd then the 3rd ... etc, it will be very complicated
Also I need to test addOnFailureListener, addOnCanceledListener ,and when they will be triggered and what the best action should be taken in these case

From the docs:
public Task<Void> setValue (Object value)
Set the data at this location to the given value. Passing null to setValue() will delete the data at the specified location. The native types accepted by this method for the value correspond to the JSON types:
Boolean
Long
Double
String
Map
List
Therefore if you have multiple setValue(), you can do the following:
DatabaseReference ref = FirebaseDatabase.getInstance().getReference("Users");
Map<String, Object> values = new HashMap<>();
values.put("name","peter");
values.put("age","100");
ref.setValue(values).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
System.out.println("completed");
}
});
Of you can use a pojo class instead of map.
https://firebase.google.com/docs/reference/android/com/google/firebase/database/DatabaseReference#setValue(java.lang.Object)

Related

How to generate Structure for Group Chat using FIREBASE?

I am developing chat app and need help regarding its group structure.
I already manage structure till groupIcon but now how to create members structure with 0 ... 1... 2... etc...?
Here is my code :
private void createGroup(String strGroupName) {
RootRef = FirebaseDatabase.getInstance().getReference("GroupDetail");
String strGroupID = RootRef.push().getKey();
HashMap<String, String> groupMap = new HashMap<>();
groupMap.put("_id", group_id);
groupMap.put("adminId", admin_id);
groupMap.put("adminName", admin_name);
groupMap.put("createdAt", created_at);
groupMap.put("groupIcon", group_icon);
RootRef.child(strGroupID).setValue(groupMap)
.addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
Toast.makeText(activity, "Group created
successfully",Toast.LENGTH_SHORT).show();
}
});
}
In the members property you have an array. I'd actually suggest first changing that model to a map like this:
members: {
"5c6260...63d00": true,
"5c6262...63d02": true
}
Reason for that are that you'll typically want each user to be a member of the chat room at most once, while an array can have the same value multiple times. Using a map automatically prevents this problem, since keys are guaranteed to be unique in a map (and in Firebase's JSON). For more on this, also see my answer here: Firebase query if child of child contains a value
The above structure you can write with a Map<String, boolean> in Java:
Map<String, boolean> members = new Map<>();
members.put("5c6260...63d00", true);
members.put("5c6262...63d02", true);
groupMap.put("members", members);

Android studio Firebase query - retrieve value from Callback function and assign it to a variable

I am a beginner so apologies for a possible silly question.
I am trying to retrieve data from a Firebase database. This works but I cannot assign the value to a string variable for use later on.
This is the asynchronous call to the database which returns the right result. (The data its querying from is static so I don't really need an asynchronous call but as far as I am aware, I don't have another option).
public static void getAnimalDetails(String strColl, final String strQueryField, final String strQueryValue,
final MyCallBack myCallback){
mfirebaseDb.collection(strColl)
.whereEqualTo(strQueryField, strQueryValue)
.get()
.addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if(task.isSuccessful()) {
for (QueryDocumentSnapshot document : task.getResult()) {
String strResult = document.get("animal_class").toString();
Log.d(TAG, "SSSS:" + strResult );
myCallback.onCallback(strResult);
}
}
}
});
}
This is the callback function passed to the method above.
public interface MyCallBack {
void onCallback(String strValFromAsyncTask);
}
Then this is where I call the asynch task and try and access the data from the callback.
This method fires on a button click
I can see via the log that the right value is populated in strAnimalClass (which is a global variable)
But when I try to use strAnimalClass outside of the call back it is null.
getAnimalDetails("animals", "animal_common_name", animal, new MyCallBack() {
#Override
public void onCallback(String strValFromAsyncTask) {
strAnimalClass = strValFromAsyncTask;
Log.d(TAG, "mmmmm:" + strAnimalClass );
}
});
Can anyone help with how to get a value like this out of the async / callback environment for use later on?
Thank you
You can't use the value outside of the callback. Or more specifically, you can use the value outside of the callback, but not before the callback has been called. This same rule applies to Firebase's onComplete and to your custom onCallback method.
You can verify that with a few log lines:
Log.d(TAG, "Before calling getAnimalDetails")
getAnimalDetails("animals", "animal_common_name", animal, new MyCallBack() {
#Override
public void onCallback(String strValFromAsyncTask) {
Log.d(TAG, "Inside onCallback");
}
});
Log.d(TAG, "After calling getAnimalDetails")
When you run this code, it logs:
Before calling getAnimalDetails
After calling getAnimalDetails
Inside getAnimalDetails
So while you can access strAnimalClass after the code that calls getAnimalDetails, it won't have the expected value yet, because onCallback wasn't called yet.
For this reason any code that needs the value(s) from the database will need to be inside onComplete or inside onCallback, or be called from within there.
Also see:
How to check a certain data already exists in firestore or not
getContactsFromFirebase() method return an empty list
Setting Singleton property value in Firebase Listener

Firestore SetOptions.mergeFields() not working as expected using POJO

I'm trying to update a specific field in a document using POJO, as written in the doc. I could use SetOptions.mergeFields(). But it's updating other fields with null instead of keeping the other fields (which excluded from mergeFields) untouched. Is it intended?
Here is my code :
UserModel userModel = new UserModel();
userModel.setStatus(0);
setTask = documentReferenceToUse.set(userModel, SetOptions.mergeFields("status"));
setTask.addOnSuccessListener(new OnSuccessListener<Void>()
{
#Override
public void onSuccess(Void aVoid)
{
if (!emitter.isDisposed())
{
emitter.onComplete();
}
}
}).addOnFailureListener(new OnFailureListener()
{
#Override
public void onFailure(#NonNull Exception e)
{
if (!emitter.isDisposed())
{
emitter.onError(e);
}
}
});
And here is my document structure :
[Solved]
Turned out the issue came from my Firebase wrapper code. So there is no actual problem on the Firebase SDL side.
Edit: After taking another closer look at your code, I found that you need to change this line of code:
setTask = documentReferenceToUse.set(model, SetOptions.mergeFields("status"));
with:
setTask = documentReferenceToUse.set(userModel, SetOptions.mergeFields("status"));
You are passing as the first argument, not the object that you have just created but another one. So, the correct object that must be used is: userModel.
You can also use another approach, by getting that entire object from the database. Having the object, you can use setters to change the value of the fileds beneath it. After you have used the setters, you can use set() method directly on the reference to add the object the database.
documentReferenceToUse.set(userModelFromDatabase);
You can also use a Map in order to make an update:
Map<String, Object> map = new HashMap<>();
map.put("status", 0);
documentReferenceToUse.update(map);

Posting timestamp to Android Firebase database doesn't work

I'm trying since a while to add timestamp on my posts in Firebase, but I'm sadly unsuccessful. I have already tried many advises from stackoverflow, but none worked. Please help me on how to add a timestamp field under each post.
I would to know what's wrong with my code.
final DatabaseReference newPost = mDatabase.push();
mDatabaseUser.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Long timestamp = (Long) dataSnapshot.getValue();
System.out.println(timestamp);
newPost.child("title").setValue(title_val);
newPost.child("desc").setValue(desc_val);
newPost.child("image").setValue(downloadUrl.toString());
newPost.child("uid").setValue(mCurrentUser.getUid());
newPost.child("username").setValue(dataSnapshot.child("name").getValue()).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
startActivity(new Intent(PostActivity.this, MainActivity.class));
}
}
});
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
mDatabaseUser.setValue(ServerValue.TIMESTAMP);
mProgress.dismiss();
Firebase Database structure:
{
"Blog":{
"-Ke1osQRFVs0fuqx9n18":{
"desc":"again again",
"uid":"FBwMzHJGP4U10LnLOwluy4BVyJ52",
"username":"OziBoo"
}
},
"Users":{
"vi6Qd1AafidNGGV4roBhdLPZYGN2":{
"image":"firebasestorage.googleapis.com/v0/b/agrodesk-b30ff.appspot.‌​com/...",
"name":"Ozi"
}
}
}
There are a lot of error and misuse in your code. Please understand this first:
ref.addValueEventListener(...) is used for listening to every changes made in data referenced by ref
ref.setValue(yourValue) is used to set the value of data referenced by ref object
setValue(...).addOnCompleteListener(...) is used if you want to execute something after value has been updated
If I understand it correctly, all of your sample code you write for writing value into database, right? But you, not knowingly, used addValueEventListener() instead.
So your code to write the value into new child inside "Blog" should be like this:
// Here I use HashMap to make it more simple
// You can (and better to) use your custom object as value container
HashMap<String, Object> value = new HashMap<>();
value.put("title", "your-title");
value.put("desc", "your-desc");
value.put("timestamp", ServerValue.TIMESTAMP);
// ... etc
// the following code will create a reference object pointing at "Blog"
DatabaseReference ref = FirebaseDatabase.getInstance().getRreference("Blog");
// the following code will make a new child inside data referenced by ref (in this case, "Blog")
DatabaseReference newBlog = ref.push();
// the following code is the code that actually update the data of referenced point
newBlog.setValue(value)
// addOnCompleteListener is optional
.addOnCompleteListener(new ... {
// code placed here will be executed when your data is updated
...
});
Hope this helps.
Note:
There I just show you what you want to achieve for this case and this case only. Please read more documentation, guide, and tutorial about Firebase Database. It might take long, but once you understand it, it's actually quite simple.

FireBase Android Need 1 value saved under a single user

I have the following data structure on firebase for the user MF0qeRA4p7djfjgXxqwFOck3m6p02. I want to get the value of item3 to populate a single field into the User interface on an Android App. I have been looking through samples on Stackoverflow, but all I have found are outdated and do not work with the current version of firebase. I'm new to firebase completely and this is my first app on android. I've got the oncreate user method to populate the users email address and add the 4 item fields, but retrieving the data I'm completely lost and I am not sure where to even begin.
-Users
---MF0qeRA4p7djfjgXxqwFOck3m6p02
------item1:"1"
------item2:"2"
------item3:"3"
------item4:"4"
According to what I can identify is, you are facing problem retrieving data from this reference. Here is the code:
final DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference("Users");
databaseReference.child("MF0qeRA4p7djfjgXxqwFOck3m6p02").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Map<String, Object> map=(Map<String, Object>)dataSnapshot.getValue();
String item3=(String)map.get("item3");
display(item3);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Hope this helps.
You can create a custom model and inside you can insert elements. Something like this:
public class Item {
private List<Object> ojects;
}
There you can save instance of Item on database. In this case you have more controll. Other case is to use push() method, that will generate a new encoded key, something like this:
mDatabase.child("items").push().put(new Object());

Categories

Resources