How to move Firebase child from one node to another in Android? - java

I am working on a project where user request for our valet services and on the other end valet accepts request.
I am using using Firebase as backend and on request customer uid is save on 'request' child.
When valet accepts request, customer uid should move from 'request' node to 'on progress' node.
How can i do that?

I recommend using this :
public void moveFirebaseRecord(Firebase fromPath, final Firebase toPath)
{
fromPath.addListenerForSingleValueEvent(new ValueEventListener()
{
#Override
public void onDataChange(DataSnapshot dataSnapshot)
{
toPath.setValue(dataSnapshot.getValue(), new Firebase.CompletionListener()
{
#Override
public void onComplete(FirebaseError firebaseError, Firebase firebase)
{
if (firebaseError != null)
{
System.out.println("Copy failed");
}
else
{
System.out.println("Success");
}
}
});
}
#Override
public void onCancelled(FirebaseError firebaseError)
{
System.out.println("Copy failed");
}
});
}
This come from this source : https://gist.github.com/katowulf/6099042 . I used it several times in my JavaEE code and also in my android app.
You pass your fromPath and toPath. This is a copy tought and not a move, so the original will remain at his original place too. If you would like to delete, you can do a set value on the fromPath just after the System.out.println("Success"); .

As of compile firebase-database:11.0.1, this is the same function with the new class references (https://firebase.google.com/support/guides/firebase-android July 05 2017)
private void moveGameRoom(final DatabaseReference fromPath, final DatabaseReference toPath) {
fromPath.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
toPath.setValue(dataSnapshot.getValue(), new DatabaseReference.CompletionListener() {
#Override
public void onComplete(DatabaseError firebaseError, DatabaseReference firebase) {
if (firebaseError != null) {
System.out.println("Copy failed");
} else {
System.out.println("Success");
}
}
});
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}

If you want to perform a move which also erases the original, you might make use of the following snippet:
// In this piece of code, "fromPath" and "toPath" parameters act like directories.
private void removeFromFirebase(final DatabaseReference fromPath, final DatabaseReference toPath, final String key) {
fromPath.child(key).addListenerForSingleValueEvent(new ValueEventListener() {
// Now "DataSnapshot" holds the key and the value at the "fromPath".
// Let's move it to the "toPath". This operation duplicates the
// key/value pair at the "fromPath" to the "toPath".
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
toPath.child(dataSnapshot.getKey())
.setValue(dataSnapshot.getValue(), new DatabaseReference.CompletionListener() {
#Override
public void onComplete(DatabaseError databaseError, DatabaseReference databaseReference) {
if (databaseError == null) {
Log.i(TAG, "onComplete: success");
// In order to complete the move, we are going to erase
// the original copy by assigning null as its value.
fromPath.child(key).setValue(null);
}
else {
Log.e(TAG, "onComplete: failure:" + databaseError.getMessage() + ": "
+ databaseError.getDetails());
}
}
});
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.e(TAG, "onCancelled: " + databaseError.getMessage() + ": "
+ databaseError.getDetails());
}
});
}

you can listen to value event on your child you want to copy it ,, and #onDataChange get reference of new child and set value dataSnapshot to this child like below sample code
FirebaseDatabase.getInstance().getReference("childYouWantToCopy")
.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
FirebaseDatabase.getInstance().getReference("ChildCopyTo").setValue(dataSnapshot.getValue());
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});

Related

How can I change the value of child in Firebase database?

I want to change the value of child "toggleStatus" under Reference "BetSlip" as shown below. The already set value is "on" so I want such that when I click the button the value of "toggleStatus" is changed to "off"
BetSlipActivity.toggleCollapse.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String timeStamp = betSlip.get(position).getTimeStamp();
String toggleStatus = betSlip.get(position).getToggleStatus();
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("BetSlip");
reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
for (DataSnapshot ds: snapshot.getChildren()) {
String timestamp = ""+ ds.child("timeStamp").getValue();
String toggleStatus = ""+ ds.child("toggleStatus").getValue();
if (timeStamp.equals(timestamp) && toggleStatus.equals("on")) {
//set value to off
}
if (timeStamp.equals(timestamp) && toggleStatus.equals("off")) {
//set value to on
}
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
}
});
If you've got the DataSnapshot for a path in the database, it's easy to get the DatabaseReference that you need to update it:
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("BetSlip");
reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
for (DataSnapshot ds: snapshot.getChildren()) {
String timestamp = ""+ ds.child("timeStamp").getValue();
String toggleStatus = ""+ ds.child("toggleStatus").getValue();
if (timeStamp.equals(timestamp) && toggleStatus.equals("on")) {
ds.child("toggleStatus").getRef().setValue("off");
}
if (timeStamp.equals(timestamp) && toggleStatus.equals("off")) {
ds.child("toggleStatus").getRef().setValue("on");
}
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
throw error.toException(); // never ignore errors
}
});
Since you're updating the node based on its existing value, strictly speaking you might need to use a transaction for it.

How to find if a child with particular value in its fields exists in Firebase?

I need to find if a child with particular value in one of its fields exists in Firebase.
Below is my database structure:
To check if a field exists,you can do this:
DatabaseReference ref=FirebaseDatabase.getInstance().getReference().child("bdxhATalcDRJCiZZcUFUJo3yrJF2");
ref.addValueEventListener(new ValueEventListener(){
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(dataSnapshot.exists()){
//then it exists
}
#Override
public void onCancelled(FirebaseError firebaseError) {
}
});
This will check if
child("bdxhATalcDRJCiZZcUFUJo3yrJF2") exists in the database.
If you do this:
ref=FirebaseDatabase.getInstance().getReference().child("bdxhATalcDRJCiZZcUFUJo3yrJF2").orderByChild("chat_id").equalTo(chatid);
then it will check if that child also exists in the database
In your case you would set up query like this:
DatabaseReference reference = FirebaseDatabase.getInstance().getReference();
Query query = reference.orderByChild("chat_id").equalTo("CHAT_ID_To_COMPARE");
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
for (DataSnapshot issue : dataSnapshot.getChildren()) {
// do something with the individual object
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
This would filter your data at server side and no need to filter data at app side.
postRef = FirebaseDatabase.getInstance().getReference().child("bdxhATalcDRJCiZZcUFUJo3yrJF2");
postRef.orderByChild("chat_id").equalTo(chat_id)
.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(dataSnapshot.exists()){
//bus number exists in Database
} else {
//bus number doesn't exists.
}
#Override
public void onCancelled(FirebaseError firebaseError) {
}
});
etEmail is an EditText
I did it for userEmail's value... as I don't have any username other than the email.
for a structure like this...
"users": {
pushId: {
"userEmail": {
}
}
}
onCreate
etEmail.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(final CharSequence s, int start, int before, int count) {
//yourFunction();
DatabaseReference databaseUsers = FirebaseDatabase.getInstance().getReference().child("users");
databaseUsers.orderByChild("userEmail").equalTo(String.valueOf(s))
.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
for (DataSnapshot issue : dataSnapshot.getChildren()) {
// do something with the individual object
//User email already exists
//do something
//return; stops the function from executing further
return;
}
} else {
// email doesn't exists.
// do something
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
#Override
public void afterTextChanged(Editable s) {
}
});
When you do the reference and you have your DataSnapshot, you can check it like this:
yourref.child("chat_id").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (!dataSnapshot.exists()) {
//Do something
}
}
exists()
Returns true if the snapshot contains a non-null value.
Also returns true if this DataSnapshot contains any data. It is slightly more efficient than using DataSnapshot.getValue() !== null.

Shortest Query of Firebase in Android?

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.

Firebase helper class

I am practicing with the Firebase library and I would like to be able to have some methods in a separated class from the Main and from this to be able to call those methods and to return for example the user.
Example FirebaseDBHelper.java
public static UserModel getUserFromId(String userId) {
final UserModel[] user = new UserModel[1];
dbRef.child("status").child(userId).addListenerForSingleValueEvent(
new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
// Get user value
user[0] = dataSnapshot.getValue(UserModel.class);
Log.d("TAG", "Value is: " + dataSnapshot.getValue());
Log.d("TAG", "User: " + user);
// ...
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.d("TAG", "getUser:onCancelled", databaseError.toException());
// ...
}
});
return user[0];
}
Main call
UserModel user = FirebaseDatabaseHelper.getUserFromId("9876");
Log.d("TAG", "UserInfo: " + user);
But I have some problems because the method getUserFromId() don't return anything.
If you know about RxJava2, it really good to go with this approach:
public Observable<UserModel> UserModel getUserFromId(String userId) {
return Observable.create(new ObservableOnSubscribe<UserModel>() {
#Override
public void subscribe(#NonNull ObservableEmitter<UserModel> e) throws Exception {
dbRef.child("status").child(userId).addListenerForSingleValueEvent(
new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
// Get user value
UserModel user = dataSnapshot.getValue(UserModel.class);
e.onNext(user);
// ...
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.d("TAG", "getUser:onCancelled", databaseError.toException());
e.onError(databaseError);
// ...
}
});
}
});
}
OR, you can define an interface callback when you get your UserModel like this
public static void getUserFromId(String userId,OnGetUser callback) {
dbRef.child("status").child(userId).addListenerForSingleValueEvent(
new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
// Get user value
user[0] = dataSnapshot.getValue(UserModel.class);
Log.d("TAG", "Value is: " + dataSnapshot.getValue());
Log.d("TAG", "User: " + user);
callback.onGetUser();
// ...
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.d("TAG", "getUser:onCancelled", databaseError.toException());
// ...
}
});
}
interface OnGetUser
{
void onGetUser();
}
OR, user[0] should have some value when onCancelled was called, like empty UserModel
Better way is to use callback from the helper class create and interface and let ure activity implement it when you call the static method pass the class when firebase gets the data call the activity callback...

Firebase - check if value exists in database

If the user is authenticated the first time I want to create a new database entry. Therefore I want to to check if the user has already an entry. I searched for some examples but my solutions are not working. My callbacks are never called. Any ideas?
if (firebaseUser == null) {
startActivityForResult(new Intent(this, AuthActivity.class), 123);
} else {
final DatabaseReference database = FirebaseDatabase
.getInstance()
.getReference()
.child("users")
.child(firebaseUser.getUid());
database.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
Log.d(TAG, "onDataChange: ye");
} else {
Log.d(TAG, "onDataChange: fuuu...");
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.d(TAG, "onCancelled: " + databaseError.getMessage());
}
});
}

Categories