Andorid
[Android]Firebase로 채팅 앱 만들기(5)
CoBool
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