ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Android]Firebase로 채팅 앱 만들기(5)
    Andorid 2022. 3. 31. 14:58

    이번에는 새로 채팅할 상대를 추가할 수 있는 검색창을 만들어보도록 하겠다.

    class AddChatRoomActivity : AppCompatActivity() {
        lateinit var binding:ActivityAddChatroomBinding
        lateinit var btn_exit: ImageButton
        lateinit var edt_opponent:EditText
        lateinit var firebaseDatabase:DatabaseReference
        lateinit var recycler_people:RecyclerView
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            binding = ActivityAddChatroomBinding.inflate(layoutInflater)
            setContentView(binding.root)
            initializeView()
            initializeListener()
            setupRecycler()
        }
    
        fun initializeView()   //뷰 초기화
        {
            firebaseDatabase = FirebaseDatabase.getInstance().reference!!
            btn_exit = binding.imgbtnBack
            edt_opponent = binding.edtOpponentName
            recycler_people = binding.recyclerPeoples
        }
        fun initializeListener()   //버튼 클릭 시 리스너 초기화
        {
            btn_exit.setOnClickListener()
            {
                startActivity(Intent(this@AddChatRoomActivity, MainActivity::class.java))
            }
    
            edt_opponent.addTextChangedListener(object :TextWatcher                  //검색 창에 입력된 글자가 변경될 때마다 검색 내용 업데이트
            {
                override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
                }
    
                override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
                }
    
                override fun afterTextChanged(s: Editable?) {
                    var adapter = recycler_people?.adapter as RecyclerUsersAdapter
                    adapter.searchItem(s.toString())                  //입력된 검색어로 검색 진행 및 업데이트
                }
            })
        }
        fun setupRecycler()   //사용자 목록 초기화 및 업데이트
        {
           recycler_people.layoutManager = LinearLayoutManager(this)
            recycler_people.adapter = RecyclerUsersAdapter(this)
        }
    }
    

    새롭게 대화를 시작할 친구를 검색할 액티비티의 전체 코드이다.

    해당 화면에 필요한 뷰들을 초기화한 후,

    edt_opponent.addTextChangedListener(object :TextWatcher                  //검색 창에 입력된 글자가 변경될 때마다 검색 내용 업데이트
            {
                override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
                }
    
                override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
                }
    
                override fun afterTextChanged(s: Editable?) {
                    var adapter = recycler_people?.adapter as RecyclerUsersAdapter
                    adapter.searchItem(s.toString())                  //입력된 검색어로 검색 진행 및 업데이트
                }
            })
    

    검색어 입력란에 단어와 일치하는 사용자를 바로 검색하게 하기 위해 리스너를 추가하였다.

    다음으로 각 사용자들의 목록을 불러올 Recycler를 만들어야 한다.

    class RecyclerUsersAdapter(val context: Context) :
        RecyclerView.Adapter<RecyclerUsersAdapter.ViewHolder>() {
        var users: ArrayList<User> =arrayListOf()        //검색어로 일치한 사용자 목록
        val allUsers: ArrayList<User> =arrayListOf()    //전체 사용자 목록
        lateinit var currnentUser: User
    
        init {
            setupAllUserList()
        }
    
        fun setupAllUserList() {        //전체 사용자 목록 불러오기
            val myUid = FirebaseAuth.getInstance().currentUser?.uid.toString()        //현재 사용자 아이디
            FirebaseDatabase.getInstance().getReference("User").child("users")   //사용자 데이터 요청
                .addValueEventListener(object : ValueEventListener {
                    override fun onCancelled(error: DatabaseError) {
                    }
    
                    override fun onDataChange(snapshot: DataSnapshot) {
                        users.clear()
                        for (data in snapshot.children) {
                            val item = data.getValue<User>()
                            if (item?.uid.equals(myUid)) {
                                currnentUser = item!!             //전체 사용자 목록에서 현재 사용자는 제외
                                continue
                            }
                            allUsers.add(item!!)              //전체 사용자 목록에 추가
                        }
                        users = allUsers.clone() as ArrayList<User>
                        notifyDataSetChanged()              //화면 업데이트
                    }
                })
        }
    
        fun searchItem(target: String) {            //검색
            if (target.equals("")) {      //검색어 없는 경우 전체 목록 표시
                users = allUsers.clone() as ArrayList<User>
            } else {
                var matchedList = allUsers.filter{ it.name!!.contains(target)}//검색어 포함된 항목 불러오기
                users.clear()
                matchedList.forEach{users.add(it)}
    }
            notifyDataSetChanged()          //화면 업데이트
        }
    
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
            val view = LayoutInflater.from(context).inflate(R.layout.list_person_item, parent, false)
            return ViewHolder(ListPersonItemBinding.bind(view))
        }
    
        override fun onBindViewHolder(holder: ViewHolder, position: Int) {
            holder.txt_name.text= users[position].name
            holder.txt_email.text= users[position].email
    
            holder.background.setOnClickListener()
    {
    addChatRoom(position)        //해당 사용자 선택 시
    }
    }
    
        fun addChatRoom(position: Int) {     //채팅방 추가
            val opponent = users[position]   //채팅할 상대방 정보
            var database = FirebaseDatabase.getInstance().getReference("ChatRoom")    //넣을 database reference 세팅
            var chatRoom = ChatRoom(         //추가할 채팅방 정보 세팅
    mapOf(currnentUser.uid!!totrue, opponent.uid!!totrue),
                null
            )
            var myUid = FirebaseAuth.getInstance().uid//내 Uid
            database.child("chatRooms")
                .orderByChild("users/${opponent.uid}").equalTo(true)       //상대방 Uid가 포함된 채팅방이 있는 지 확인
                .addListenerForSingleValueEvent(object : ValueEventListener {
                    override fun onCancelled(error: DatabaseError) {}
                    override fun onDataChange(snapshot: DataSnapshot) {
                        if (snapshot.value== null) {              //채팅방이 없는 경우
                            database.child("chatRooms").push().setValue(chatRoom).addOnSuccessListener{// 채팅방 새로 생성 후 이동
                                goToChatRoom(chatRoom, opponent)
    }
    } else {
                            context.startActivity(Intent(context, MainActivity::class.java))
                            goToChatRoom(chatRoom, opponent)                    //해당 채팅방으로 이동
                        }
    
                    }
                })
        }
    
        fun goToChatRoom(chatRoom: ChatRoom, opponentUid: User) {       //채팅방으로 이동
            var intent = Intent(context, ChatRoomActivity::class.java)
            intent.putExtra("ChatRoom", chatRoom)       //채팅방 정보
            intent.putExtra("Opponent", opponentUid)    //상대방 정보
            intent.putExtra("ChatRoomKey", "")   //채팅방 키
            context.startActivity(intent)
            (context as AppCompatActivity).finish()
        }
    
        override fun getItemCount(): Int {
            return users.size
        }
    
        inner class ViewHolder(itemView: ListPersonItemBinding) :
            RecyclerView.ViewHolder(itemView.root) {
            var background = itemView.background
            var txt_name = itemView.txtName
            var txt_email = itemView.txtEmail
        }
    
    }
    
    

    사용자 목록을 불러오는 Recycler의 전체 코드다.

     fun setupAllUserList() {        //전체 사용자 목록 불러오기
            val myUid = FirebaseAuth.getInstance().currentUser?.uid.toString()        //현재 사용자 아이디
            FirebaseDatabase.getInstance().getReference("User").child("users")   //사용자 데이터 요청
                .addValueEventListener(object : ValueEventListener {
                    override fun onCancelled(error: DatabaseError) {
                    }
    
                    override fun onDataChange(snapshot: DataSnapshot) {
                        users.clear()
                        for (data in snapshot.children) {
                            val item = data.getValue<User>()
                            if (item?.uid.equals(myUid)) {
                                currnentUser = item!!             //전체 사용자 목록에서 현재 사용자는 제외
                                continue
                            }
                            allUsers.add(item!!)              //전체 사용자 목록에 추가
                        }
                        users = allUsers.clone() as ArrayList<User>
                        notifyDataSetChanged()              //화면 업데이트
                    }
                })
        }
    
    

    사용자들의 정보가 포함된 데이터베이스인 User 데이터베이스에 접근하여 목록을 가져와 저장한 뒤,

    현재 사용자의 uid와 비교하여 자신은 제외한다.

     fun searchItem(target: String) {            //검색
            if (target.equals("")) {      //검색어 없는 경우 전체 목록 표시
                users = allUsers.clone() as ArrayList<User>
            } else {
                var matchedList = allUsers.filter{ it.name!!.contains(target)}//검색어 포함된 항목 불러오기
                users.clear()
                matchedList.forEach{users.add(it)}
    }
            notifyDataSetChanged()          //화면 업데이트
        }
    

    사용자가 입력란에 검색어를 넣는 경우 위 코드를 실행하여 불러온 전체 목록에서 검색어를 포함하는 목록만 남겨 리스트를 업데이트 한다.

     override fun onBindViewHolder(holder: ViewHolder, position: Int) {
            holder.txt_name.text= users[position].name
            holder.txt_email.text= users[position].email
    
            holder.background.setOnClickListener()
    {
    addChatRoom(position)        //해당 사용자 선택 시
    }
    }
    
        fun addChatRoom(position: Int) {     //채팅방 추가
            val opponent = users[position]   //채팅할 상대방 정보
            var database = FirebaseDatabase.getInstance().getReference("ChatRoom")    //넣을 database reference 세팅
            var chatRoom = ChatRoom(         //추가할 채팅방 정보 세팅
    mapOf(currnentUser.uid!!totrue, opponent.uid!!totrue),
                null
            )
            var myUid = FirebaseAuth.getInstance().uid//내 Uid
            database.child("chatRooms")
                .orderByChild("users/${opponent.uid}").equalTo(true)       //상대방 Uid가 포함된 채팅방이 있는 지 확인
                .addListenerForSingleValueEvent(object : ValueEventListener {
                    override fun onCancelled(error: DatabaseError) {}
                    override fun onDataChange(snapshot: DataSnapshot) {
                        if (snapshot.value== null) {              //채팅방이 없는 경우
                            database.child("chatRooms").push().setValue(chatRoom).addOnSuccessListener{// 채팅방 새로 생성 후 이동
                                goToChatRoom(chatRoom, opponent)
    }
    } else {
                            context.startActivity(Intent(context, MainActivity::class.java))
                            goToChatRoom(chatRoom, opponent)                    //해당 채팅방으로 이동
                        }
    
                    }
                })
        }
    

    항목을 선택 시 채팅방 목록 중에서 해당 사용자의 Uid가 포함된 채팅방을 찾아 해당 채팅방 화면으로 이동하고, 없으면 새로 데이터베이스에 채팅방을 삽입한다.

    완성된 화면이다.

    참조

    https://m.blog.naver.com/zoown13/222094002924https://cionman.tistory.com/72https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=traeumen927&logNo=221493556497https://lasbe.tistory.com/19

Designed by Tistory.