본문 바로가기
Java/AndroidStudio

Android - FireBase 이용 1:1 실시간 채팅 구현

by 하니__ 2024. 6. 21.

 

 

우선은 목표를 간단하게 설정했다

 

 

 Android - FireBase 사용 설정

 

 

 

 

앞부분의 환경설정과 회원가입,로그인은 필수라서 참고하고

 

 

원하는건 첫 화면

즉 메인화면으로 들어왔을때

 

1. 로그인을 하였는지 확인후 로그인이 안됐다면 로그인과 회원가입이 되는 액티비티로 이동

 

 

2. 로그인을 했다면 회원들의 목록이 떠 그 이름을 누르면 그 사람과 채팅을 시작

 

 

3. 나의 메세지는 오른쪽 상대의 메세지는 왼쪽에 

실시간으로 업데이트 되도록 구현

 

 

 

코드 설명에 앞서
모든 코드를 올리진 않았고,
참고만 하시기 바랍니다

 

 

 

 

1. 로그인이 안됐다면 로그인페이지로 이동
// Firebase 인증 및 데이터베이스 초기화
mAuth = FirebaseAuth.getInstance(); // 파이어베이스 인증객체 초기화
currentUser = mAuth.getCurrentUser(); //현재 로그인한 유저 정보 가져오기
if (currentUser == null) {
    // 사용자가 로그인되어 있지 않은 경우, 로그인 화면으로 이동
    Intent intent = new Intent(ChatActivity.this, LoginActivity.class);
    startActivity(intent);
    finish(); 
    return; 
}

 

로그인페이지에서도 사용한

인증관련한 FirebaseAuth에서 .getInstance() 를 사용,

그리고 그것을 변수로 저장후

이번엔

.getCurrentUser() 로 사용자를 특정

 

if문으로 CurrentUser가 null이라면 

로그인을 하지않은 경우이기때문에 인텐트를 띄워 로그인페이지로 이동시켜주고

finish()와 리턴



2. 로그인을 해서 돌아온다면 이제 채팅창이 보여야한다

화면설정은 간단하게 해준뒤

 

 

adapter = new UserAdapter(this, userList);
listViewUsers.setAdapter(adapter);

 

로 어댑터에 연결 시켜준다

 

해당 어댑터는

public class UserAdapter extends ArrayAdapter<User> {
    public UserAdapter(Context context, List<User> users) {
        super(context, 0, users);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        User user = getItem(position);

        if (convertView == null) {
            convertView = LayoutInflater.from(getContext()).inflate(R.layout.user_item, parent, false);
        }

        TextView textViewUserName = convertView.findViewById(R.id.textViewUserName);
        textViewUserName.setText(user.getUserName());

        return convertView;
    }
}

 

로 이루어져있고

getItem(position)으로 해당 위치의 유저를 판별후

유저의 이름을 표시하여

그 해당 유저와의 채팅방임을 알린다

 

listViewUsers.setOnItemClickListener(new AdapterView.OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        User selectedUser = userList.get(position);
        Intent intent = new Intent(MainActivity.this, ChatActivity.class);
        intent.putExtra("selectedUserId", selectedUser.getUserId());
        startActivity(intent);
    }
});

그리고 해당 유저이름을 클릭시 그 유저와의 채팅방으로 이동을 시켜준다

 

 

userId = currentUser.getUid(); 
selectedUserId = getIntent().getStringExtra("selectedUserId");
receiverId = selectedUserId;

 

현재 로그인한 나의 아이디를 가져오고

상대의 아이디도 가져온다

 

messagesList = new ArrayList<>();
adapter = new MessageAdapter(this, messagesList, userId);

recyclerViewMessages.setLayoutManager(new LinearLayoutManager(this));
recyclerViewMessages.setAdapter(adapter);

'messages'의 레퍼런스 초기화를 해준뒤

메세지 목록을 저장할 ArrayList 초기화,

 

그 다음은 리사이클러뷰를 통해 어댑터와 연결을 해준다

 

해당 어댑터에서 몇가지

 

void bind(Message message) {
    messageTextView.setText(message.getText());

    // 상대방의 이름 가져오기
    DatabaseReference userRef = FirebaseDatabase.getInstance().getReference("users").child(message.getSenderId());
    userRef.addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
            User user = dataSnapshot.getValue(User.class);
            if (user != null) {
                senderNameTextView.setText(user.getUserName());
            }
        }

        @Override
        public void onCancelled(@NonNull DatabaseError databaseError) {
            // Error handling
        }
    });
}

 

상대방의 이름을 가져와 메세지와 함께 이름을 띄워주도록 한다

 

 

@NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view;
        if (viewType == VIEW_TYPE_MESSAGE_SENT) {
            view = LayoutInflater.from(context).inflate(R.layout.message_item_right, parent, false);
            return new SentMessageHolder(view);
        } else {
            view = LayoutInflater.from(context).inflate(R.layout.message_item_left, parent, false);
            return new ReceivedMessageHolder(view);
        }
    }

 

로 설정하여

 

나의 메세지는 오른쪽에 상대의 메세지는 왼쪽에 오게끔 해준다

R.layout.message_item_left

R.layout.message_item_right

 

 

 

메세지가 왼쪽과 오른쪽으로 오게끔 설정되어있다

 

 

그래서 채팅방의 화면은

이렇게 설정 되어있는데

채팅방 목록과 똑같이 메세지 리스트들이 쌓이게 되며

 

아래의 메세지입력칸에 메세지를 입력하고

보내기 버튼을 클릭하면 내 메세지와 상대의 메세지가 실시간 업데이트가 되는 화면

 

 

databaseMessages.addValueEventListener(new ValueEventListener() {
    @Override
    public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
        messagesList.clear();
        for (DataSnapshot postSnapshot : dataSnapshot.getChildren()) {
            Message message = postSnapshot.getValue(Message.class);
            if (message != null && message.getSenderId() != null && message.getReceiverId() != null) {
                if ((message.getSenderId().equals(userId) && message.getReceiverId().equals(receiverId)) ||
                        (message.getSenderId().equals(receiverId) && message.getReceiverId().equals(userId))) {
                    messagesList.add(message);
                }
            }
        }
        adapter.notifyDataSetChanged();
        // 스크롤을 맨 아래로 이동하려면 필요한 코드를 여기에 추가할 수 있습니다.
        recyclerViewMessages.smoothScrollToPosition(messagesList.size() - 1);
    }

    @Override
    public void onCancelled(@NonNull DatabaseError databaseError) {
        Toast.makeText(ChatActivity.this, "Failed to load messages.", Toast.LENGTH_SHORT).show();
    }
});

 

를 통해서 메세지목록을 실시간으로 업데이트 하게 만들어주는데

 

시작할때

messagesList.clear( ) 를 통하여

기존 메시지 목록 초기화를 해주고

 

if (message != null && message.getSenderId() != null && message.getReceiverId() != null) { if ((message.getSenderId().equals(userId) && message.getReceiverId().equals(receiverId)) || (message.getSenderId().equals(receiverId) && message.getReceiverId().equals(userId))) 

부분을 통해 현재 사용자와 선택한 사용자 간의 메시지만 목록에 추가

 

listViewMessages.smoothScrollToPosition(messagesList.size() - 1)

를 통해 새 메시지가 추가되면 자동으로

목록의 마지막으로 스크롤을 내려준다

 

즉, 새로운 메세지가 올라오면

메세지목록들이 위로 올라가면서

새로운 메세지가 텍스트 입력칸 위쪽으로 한칸 한칸 쌓이게되는것

 

 

 

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

그리고 메세지 보내기 버튼 온클릭이벤트를 만들어

메세지보내기 함수로 처리

 

 

private void sendMessage() {
    String message = editText.getText().toString().trim();
    if (!TextUtils.isEmpty(message)) {
        // Firebase Database에 메시지를 보내는 코드
        String messageId = databaseMessages.push().getKey();
        Message newMessage = new Message(message, userId, receiverId);
        if (messageId != null) {
            databaseMessages.child(messageId).setValue(newMessage);
            editText.setText("");
        }
    } else {
        Toast.makeText(this, "Enter a message", Toast.LENGTH_SHORT).show();
    }
}

입력한 메세지를 가져오고

메세지가 비어있지않다면

새로운 메세지의 ID와 새로운 메세지의 객체 생성

 

그리고 데이터베이스에 저장후

텍스트 입력칸을 초기화(공백) 시켜준다

 

메세지가 비어있다면 메세지를 입력하라는 토스트메세지를 남겨주자

 

 

 

바로바로 실시간 채팅이 가능해졌다

 

https://www.canva.com/design/DAGIuk9BLoU/mxoAoPSmI9KpsFQZAmRNKQ/view?utm_content=DAGIuk9BLoU&utm_campaign=share_your_design&utm_medium=link&utm_source=shareyourdesignpanel

'Java > AndroidStudio' 카테고리의 다른 글

Android - FireBase 사용 설정  (0) 2024.06.20
Android - 구글맵 이용 주변검색  (0) 2024.06.19
Android - 구글맵 마커 표시  (0) 2024.06.19
Android - 이메일 형식 체크  (0) 2024.06.19
Android - GPS 사용  (0) 2024.06.18