-

Firebase 채팅 기능 구현

건휘맨 2024. 6. 21. 18:22

 

파이어베이스 스토리지, 리얼타임 데이터베이스

채팅에서 쓸 서클이미지뷰, 이미지 전송을 위한 글라이드를 사용하기 위해 build.gradle app 에 추가

 

상단

 

build.gradle 프로젝트에 추가

 

manifest

인터넷 연결과

스토리지 사용

 

 

파이어베이스 사용 위해서 받은 json 파일 앱 수준으로 추가

 

 

채팅을 저장할 리스트

 

이미지 저장을 위한 파이어베이스 스토리지와

채팅을 위한 파이어베이스 리얼타임 데이터베이스를 참조하는 참조 변수 선언

 

DatabaseReference myRef;는 Firebase Realtime Database의 특정 경로를 참조하기 위한 변수 DatabaseReference는 Firebase Realtime Database에서 데이터 읽기, 쓰기, 업데이트, 삭제 등의 작업을 수행하기 위한 인터페이스를 제공

 

참조 변수 초기화

 

storageReference와 databaseReference는 Firebase Storage와

Realtime Database의 특정 경로를 가리키도록 초기화

 

채팅을 실시간 업데이트 하기 위해서 리스너를 설정

DataSnapshot은 Firebase Realtime Database에서 제공하는 클래스

데이터베이스에서 특정 위치의 데이터를 캡처하는 역할

DataSnapshot 객체는 데이터를 읽는 메소드 제공

getValue 이용해서 model 에 ChatData 로 받은 데이터를 chatList 에 add

add 될때 실시간으로 변경을 알리고 스크롤을 밑으로 내림 (밑으로 내리는 이유는 최신 채팅을 보기 위해서)

 

스크롤 함수

 

 

입력한 닉네임, 메시지, 시간을 데이터베이스로 보내고 저장 후 메시지 입력란을 초기화

 

이미지 전송 버튼

 

버튼을 누르면 다이얼로그가 띄워짐

갤러리로 이동, 카메라로 이동 버튼 생성

무엇을 누르냐에 따라서 각각 다른 함수가 실행

 

이 메서드는 갤러리로 이동을 눌렀을 때 갤러리를 실행

리퀘스트 코드 1을 사용하여, 갤러리에서 이미지를 선택한 후 결과를 onActivityResult 로 전달

 

카메라로 이동

 

갤러리로 이동해서 이미지를 선택하면 케이스 1 실행

이미지 받아서 변환해서 Firebase Storage에 업로드

카메라도 똑같음 ㅎㅎ

 

Bitmap 이미지를 Firebase Storage에 업로드하고

업로드가 완료되면 다운로드 URL을 얻어와서 이를 이용해 메시지 보내는 역할

 

Bitmap 객체를 Uri로 변환

 

입력한 닉네임, url, 시간을 데이터베이스로 보내고 저장

 

 

package com.gh.firebasechatprototype.model;

public class ChatData {

    private String messageId;
    private String messageContent;
    private String senderId;
    private String senderNickname;
    private String imageUrl; // 이미지 URL 필드 추가
    private long timestamp;

    public ChatData() {
        // Default constructor required for Firebase
    }

    public ChatData(String messageId, String messageContent, String senderId, String senderNickname, long timestamp, String imageUrl) {
        this.messageId = messageId;
        this.messageContent = messageContent;
        this.senderId = senderId;
        this.senderNickname = senderNickname;
        this.timestamp = timestamp;
        this.imageUrl = imageUrl; // 이미지 URL 초기화
    }

    public String getMessageId() {
        return messageId;
    }

    public void setMessageId(String messageId) {
        this.messageId = messageId;
    }

    public String getMessageContent() {
        return messageContent;
    }

    public void setMessageContent(String messageContent) {
        this.messageContent = messageContent;
    }

    public String getSenderId() {
        return senderId;
    }

    public void setSenderId(String senderId) {
        this.senderId = senderId;
    }

    public String getSenderNickname() {
        return senderNickname;
    }

    public void setSenderNickname(String senderNickname) {
        this.senderNickname = senderNickname;
    }

    public String getImageUrl() {
        return imageUrl;
    }

    public void setImageUrl(String imageUrl) {
        this.imageUrl = imageUrl;
    }

    public long getTimestamp() {
        return timestamp;
    }

    public void setTimestamp(long timestamp) {
        this.timestamp = timestamp;
    }
}

모델 ㅋㅋ

 

 

아답타

 

 

RecyclerView에서 다양한 종류의 뷰를 효율적으로 관리하기 위해서 뷰 타입 상수 정의

채팅 애플리케이션에서는 텍스트 메시지와 이미지 메시지, 
그리고 본인과 다른 사용자가 보낸 메시지를 구분해야 하므로 여러 종류의 뷰가 필요

 

뷰 타입 분리

상수에 따라 연결할 xml 파일 결정

 

상수에 따라 화면에 표시 

 

 

 

조건문으로 내 이미지, 내 텍스트, 상대 이미지, 상대 텍스트의 상수값을 결정

 

 

 

public class MyMessageViewHolder extends RecyclerView.ViewHolder {
        private TextView txtMyMessage;
        private TextView txtMyName;
        private TextView txtMyTime;

        public MyMessageViewHolder(@NonNull View itemView) {
            super(itemView);
            txtMyMessage = itemView.findViewById(R.id.txtMyMessage);
            txtMyName = itemView.findViewById(R.id.txtMyName);
            txtMyTime = itemView.findViewById(R.id.txtMyTime);
        }

        public void bind(ChatData chat) {
            txtMyName.setText(chat.getSenderNickname());
            txtMyMessage.setText(chat.getMessageContent());
            txtMyTime.setText(getFormattedTime(chat.getTimestamp()));
        }

        private String getFormattedTime(long timestamp) {
            SimpleDateFormat sdf = new SimpleDateFormat("HH:mm", Locale.getDefault());
            return sdf.format(new Date(timestamp));
        }
    }

    public class OtherMessageViewHolder extends RecyclerView.ViewHolder {
        private TextView txtOtherMessage;
        private TextView txtOtherName;
        private TextView txtOtherTime;

        public OtherMessageViewHolder(@NonNull View itemView) {
            super(itemView);
            txtOtherMessage = itemView.findViewById(R.id.txtOtherMessage);
            txtOtherName = itemView.findViewById(R.id.txtOtherName);
            txtOtherTime = itemView.findViewById(R.id.txtOtherTime);
        }

        public void bind(ChatData chat) {
            txtOtherName.setText(chat.getSenderNickname());
            txtOtherMessage.setText(chat.getMessageContent());
            txtOtherTime.setText(getFormattedTime(chat.getTimestamp()));
        }

        private String getFormattedTime(long timestamp) {
            SimpleDateFormat sdf = new SimpleDateFormat("HH:mm", Locale.getDefault());
            return sdf.format(new Date(timestamp));
        }
    }

    public class MyImageViewHolder extends RecyclerView.ViewHolder {
        private ImageView imgMessage;
        private TextView txtSenderName;
        private TextView txtMessageTime;

        public MyImageViewHolder(@NonNull View itemView) {
            super(itemView);
            imgMessage = itemView.findViewById(R.id.imgMessage);
            txtSenderName = itemView.findViewById(R.id.txtSenderName);
            txtMessageTime = itemView.findViewById(R.id.txtMessageTime);
        }

        public void bind(ChatData chat) {
            txtSenderName.setText(chat.getSenderNickname());
            Glide.with(itemView.getContext())
                    .load(chat.getImageUrl())
                    .error(R.drawable.ic_launcher_foreground)
                    .listener(new RequestListener<Drawable>() {
                        @Override
                        public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
                            Log.e("Glide", "Error loading image", e);
                            return false;
                        }

                        @Override
                        public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
                            return false;
                        }
                    })
                    .into(imgMessage);
            txtMessageTime.setText(getFormattedTime(chat.getTimestamp()));
        }

        private String getFormattedTime(long timestamp) {
            SimpleDateFormat sdf = new SimpleDateFormat("HH:mm", Locale.getDefault());
            return sdf.format(new Date(timestamp));
        }
    }

    public class OtherImageViewHolder extends RecyclerView.ViewHolder {
        private ImageView imgMessageOther;
        private TextView txtOtherSenderName;
        private TextView txtOtherMessageTime;

        public OtherImageViewHolder(@NonNull View itemView) {
            super(itemView);
            imgMessageOther = itemView.findViewById(R.id.imgMessageOther);
            txtOtherSenderName = itemView.findViewById(R.id.txtOtherSenderName);
            txtOtherMessageTime = itemView.findViewById(R.id.txtOtherMessageTime);
        }

        public void bind(ChatData chat) {
            txtOtherSenderName.setText(chat.getSenderNickname());
            Glide.with(itemView.getContext())
                    .load(chat.getImageUrl())
                    .error(R.drawable.ic_launcher_foreground)
                    .listener(new RequestListener<Drawable>() {
                        @Override
                        public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
                            Log.e("Glide", "Error loading image", e);
                            return false;
                        }

                        @Override
                        public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
                            return false;
                        }
                    })
                    .into(imgMessageOther);
            txtOtherMessageTime.setText(getFormattedTime(chat.getTimestamp()));
        }

        private String getFormattedTime(long timestamp) {
            SimpleDateFormat sdf = new SimpleDateFormat("HH:mm", Locale.getDefault());
            return sdf.format(new Date(timestamp));
        }
    }
}

화면에 표시할 것들 

이미지는 글라이드

'-' 카테고리의 다른 글

영화 추천 시스템 만들기  (0) 2024.05.27