2

Aim

Save data within the Group Chat node

Current Database Tree

enter image description here

Within the Group Chats node, the user's messages will be sent and stored within the user's selected group chat.

As shown in the database tree, the user has sent a message saying "Hello" and his name is retrieved from the Users node

Desired Database Tree

enter image description here

The ---Msg ID--- is automatically generated

The ---User ID--- is retreived from the Users node

Problem

The function to allow the user to send message Only Worked Once which was the FIRST time. The following times that the app was deployed, it crashed when the user logged in.

Error - Logcat

com.google.firebase.database.DatabaseException: Failed to convert value of type java.util.HashMap to String

ChatActivity Class - Send Chat Message function

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_chat);

        jGroupChatName = getIntent().getExtras().get("groupChatName").toString();
        jUserName = getIntent().getExtras().get("groupUserName").toString();
        jUserNeighbourhood = getIntent().getExtras().get("groupUserHome").toString();

        jChatToolbar = (Toolbar) findViewById(R.id.allUSersToolBar);

        jFirebaseCurrentUser = FirebaseAuth.getInstance().getCurrentUser();

        /*UserID Start - I was trying to retrieve the current user ID and add it to the Group Chat node, 
          under the selected Group Chat */
        assert jFirebaseCurrentUser != null;
        final String currentUserID = jFirebaseCurrentUser.getUid();
        jChatRoot = FirebaseDatabase.getInstance().getReference().child("Group Chats").child(jGroupChatName).child(currentUserID);
        /*UserID End*/

        jChatMessageText = (EditText) findViewById(R.id.chatMessageText);
        jChatSendTextBtn = (ImageButton) findViewById(R.id.chatSendTextBtn);

        jChatSendTextBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                Map<String, Object> groupMap = new HashMap<String, Object>();
                jGroupKey = jChatRoot.push().getKey();
                jChatRoot.updateChildren(groupMap);

                // Based on the UserID code at the top, the "currentUserID" is added as shown below
                // My intentions are to have the UserID saved under the name of the Group Chat
                // jGroupKey = (Name of selected Group Chat)

                DatabaseReference groupMessageRoot = jChatRoot.child(jGroupKey).child(currentUserID);
                Map<String, Object> groupMap2 = new HashMap<String, Object>();
                groupMap2.put("name", jUserName);
                groupMap2.put("msg", jChatMessageText.getText().toString());

                groupMessageRoot.updateChildren(groupMap2);
            }
        });
    }

Linked Question

Android - Firebase - Send Users to Chat Room

Future Implementations

In the future, I intend to allow the user to send pictures and video recordings by writing a code to allow the user to access their phone camera or gallery and send the pics and vids data into the Group Chats node, under the selected Group name. I would also like to retrieve data after sending, but of course, I will leave those in future questions if I am unable to solve them.

The Employee 123
  • 494
  • 1
  • 14
  • 27
  • I see that you use John Smith's UID as key in "Group Chats/Android" path. This is not the same key in "Users" path, is that alright for you? – Mehmed Sep 28 '17 at 22:50
  • Secondly, what is your purpose when `jChatSendTextBtn` is clicked? Are you trying to add new record under "Group Chats/Android/-Kv7M..." or update it? – Mehmed Sep 28 '17 at 23:29
  • Yes, I wanted to use John Smith's UID for the "Group Chats/Android/-Kv7MYc..." path. It should look like "Group Chats/Android/-Kv7MYc.../OHPiy" The reason for this is because I want messages sent by the user to be kept under that user's ID which will be located under the "Group Chats/Selected Group" path For the Second comment, yes my purpose for `jChatSendTextBtn` is to add a new record under "Group Chats/Android/-Kv7MYc.../(User who sent it". Not update. I guess I should add in a `.push()` right? – The Employee 123 Sep 29 '17 at 07:36
  • @Mehmed Please provide me a solution to this... =D – The Employee 123 Sep 29 '17 at 11:40
  • Need 5 hours to be able to look at this. Your structure is still a misery to me so I have to figure it out first :) – Mehmed Sep 29 '17 at 12:12
  • Okay Thank you @Mehmed !!! =D If you need to see more of my codes or another screenshot of my database, do let me know. I'll post it in my question. Thanks again =D – The Employee 123 Sep 29 '17 at 12:15
  • @Mehmed can you please help me answer this question? https://stackoverflow.com/questions/46527759/android-firebase-retrieving-data – The Employee 123 Oct 02 '17 at 16:52

1 Answers1

1

Branching of your desired database is unnecessary. You are creating an unnecessary level using UID of users. Instead, merge this layer down, i.e. combine uid, message and name. You can then use someRef.orderByKey("uid").equalTo("<user_uid>") in case you need specific user's records within that path, for example chat messages.

So, create a class called ChatMessage:

public class ChatMessage {

    private String uid;
    private String name;
    private String message;
    private Long creationTime;

    public ChatMessage() {
        // Default constructor required for calls to DataSnapshot.getValue(ChatMessage.class)
    }

    public ChatMessage(String uid, String name, String message) {
        this.uid = uid;
        this.name = name;
        this.message = message;
    }

    public String getUid() {
        return uid;
    }

    public void setUid(String uid) {
        this.uid = uid;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public java.util.Map<String, String> getCreationTime() {
        return ServerValue.TIMESTAMP;
    }

    @Exclude
    public Long getCreationTimeLong() {
        return creationTime;
    }

    public void setCreationTime(Long creationTime) {
        this.creationTime = creationTime;
    }
}

Then update your code as follows:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_chat);

    chatGroupName = getIntent().getStringExtra(CHAT_GROUP_NAME);
    userKey = getIntent().getStringExtra(USER_KEY);
    user = getIntent().getParcelableExtra(USER);

    jChatToolbar = (Toolbar) findViewById(R.id.allUSersToolBar);
    jChatMessageText = (EditText) findViewById(R.id.chatMessageText);
    jChatSendTextBtn = (ImageButton) findViewById(R.id.chatSendTextBtn);

    jChatSendTextBtn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            sendMessage();
        }
    });
}

private void sendMessage() {
    String userMessage = jChatMessageText.getText().toString();
    chatGroupRef = FirebaseDatabase.getInstance().getReference().child("Group Chats").child(chatGroupName);

    if (!TextUtils.isEmpty(userMessage)) {
        String newChatMessageKey = chatGroupRef.push().getKey();
        ChatMessage newChatMessage = new ChatMessage(userKey, user.getName(), userMessage);
        chatGroupRef.child(newChatMessageKey).setValue(newChatMessage);
    }
}
Mehmed
  • 2,880
  • 4
  • 41
  • 62