Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Loop when trying to change value in Firebase database on android

I'm currently trying to write a messaging app and found a bug I've been stuck with for two weeks and just can't get anywhere.

The app works as follows: When a user is contacted, the status of both users should be set to "blocked" so that no one else can contact them. This is how I implemented it in the program:

the send button:

openNewChatButton = (Button) findViewById(R.id.mainSendButton);
        openNewChatButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String checkText = sendMainMessage.getText().toString();
                if (checkText.isEmpty()) {
                    Toast.makeText(MainActivity.this, "Bitte verfasse vorher eine Nachricht.", Toast.LENGTH_SHORT).show();
                } else {
                    sendMessageToUser();
                }
            }
        });

Creating message and sending it:

public void sendMessageToUser() {
        mUsersDatabaseForRandomChatUser.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                key = sampleUserID;
                if (current_uid.equals(key) || key == null || key == "") {
                    Toast.makeText(MainActivity.this, "Keinen passenden Chatpartner gefunden!", Toast.LENGTH_SHORT).show();
                } else {
                    Intent newMessageIntent = new Intent(MainActivity.this, ChatActivity.class);
                    newMessageIntent.putExtra("chatuser_id", key);
                    newMessageIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
                    newMessageIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
                    sendChatMessage();
                    finish();
                    setYouChatID();
                    changeStateOfUserToBlocked();
                    startActivity(newMessageIntent);

                }
            }

            @Override
            public void onCancelled(DatabaseError databaseError) {
            }
        });
    }



private void sendChatMessage() {
        String message = sendMainMessage.getText().toString();
        if (!TextUtils.isEmpty(message)) {
            String current_user_ref = "messages/" + current_uid + "/" + key;
            String chat_user_ref = "messages/" + key + "/" + current_uid;

            DatabaseReference user_message_push = mRootReference.child("Messages").child(current_uid).child(key).push();
            String push_id = user_message_push.getKey();

            Map messageMap = new HashMap();
            messageMap.put("message", message);
            messageMap.put("seen", false);
            messageMap.put("type", "text");
            messageMap.put("time", ServerValue.TIMESTAMP);
            messageMap.put("from", current_uid);

            sendMainMessage.setText("");

            Map messageUserMap = new HashMap();
            messageUserMap.put(current_user_ref + "/" + push_id, messageMap);
            messageUserMap.put(chat_user_ref + "/" + push_id, messageMap);

            mRootReference.updateChildren(messageUserMap, new DatabaseReference.CompletionListener() {
                @Override
                public void onComplete(DatabaseError databaseError, DatabaseReference databaseReference) {
                    if (databaseError != null)
                        Log.d("CHAT_LOG", databaseError.getMessage().toString());
                }
            });

        }
    }

Changing status of user and setting current chatpartner:

private void setYouChatID() {
    DatabaseReference youChatID = mRootReference.child("Users").child(mAuth.getCurrentUser().getUid()).child("youchatid");
    youChatID.setValue(key);

    DatabaseReference youChatIDChatUser = mRootReference.child("Users").child(key).child("youchatid");
    youChatIDChatUser.setValue(current_uid);
}

private void changeStateOfUserToBlocked() {
    DatabaseReference stateDatabaseChatUser = mRootReference.child("Users").child(key).child("status");
    stateDatabaseChatUser.setValue("blocked");

    DatabaseReference stateDatabaseUser = mRootReference.child("Users").child(mAuth.getCurrentUser().getUid()).child("status");
    stateDatabaseUser.setValue("blocked");
}

Up to here everything works perfectly.

enter image description here

Now, when the chat is closed, the status of both users should be set back to "free" and the current chatPartner (youchatid) should be set to "default".

   @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mAuth = FirebaseAuth.getInstance();
        mCurrentUserId = mAuth.getCurrentUser().getUid();
        mRootReference = FirebaseDatabase.getInstance().getReference();
        mChatUserId = getIntent().getStringExtra("giveUserChatID");

        setContentView(R.layout.activity_securty_pop_up);
        bestaetigenButton = findViewById(R.id.bestaetigenButton);
        bestaetigenButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(SecurtyPopUpActivity.this, MainActivity.class);
                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
                intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
                finish();
                startActivity(intent);
                changeStateOfUserToFree();
                removeYouChatID();


            }
        });
    }

   public void changeStateOfUserToFree() {
        DatabaseReference stateDatabaseChatUser = mRootReference.child("Users").child(mChatUserId).child("status");
        stateDatabaseChatUser.setValue("free");

        DatabaseReference stateDatabaseUser = mRootReference.child("Users").child(mAuth.getCurrentUser().getUid()).child("status");
        stateDatabaseUser.setValue("free");
    }

  public void removeYouChatID() {
        DatabaseReference youChatID = mRootReference.child("Users").child(mAuth.getCurrentUser().getUid()).child("youchatid");
        youChatID.setValue("default");

        DatabaseReference youChatIDChatUser = mRootReference.child("Users").child(mChatUserId).child("youchatid");
        youChatIDChatUser.setValue("default");
    }

This is exactly where the problem starts!

It looks as if the program got caught in a loop at this point. Both attributes are changed briefly, but return to the old value and the activity is opened again.

However, if I close all tasks on my smartphone (including my app) and try the same thing again, it works without problems. After the first time, however, it does not work again and the loop starts over, as you can see from the video.

Because this is not so easy to understand, I added a video here: https://www.youtube.com/watch?v=fNgjYbgB44w

I am more than desperate and just can't find a solution to this problem? Maybe one of you will have an idea.

like image 249
Ron Makila Avatar asked May 15 '18 19:05

Ron Makila


2 Answers

Always use

addListenerForSingleValueEvent()

if any database modification or any function to be performed inside the dataChange method

like image 153
Jinson Paul Avatar answered Nov 07 '22 23:11

Jinson Paul


I can't believe that the solution was so "simple". All the time i was thinking that the ValueEventListeners in the setYouChatID() method were wrong. However, in the sendMessageToUser() method there was still an addValueEventListener() instead of an addListenerForSingleValueEvent(). After I fixed this, the problem was gone!

like image 34
Ron Makila Avatar answered Nov 07 '22 23:11

Ron Makila