Android- 로그인 및 채팅기능(Firebase)
-
28일에 했던 로그인기능에다가 채팅기능까지 더해졌다. 내가보낸메세지는 오른쪽, 상대방이 보낸 메세지는 왼쪽에 위치한다.
-
로그인 기능 코드는 다똑같으니까 메세지 추가하는 부분의 코드만 추가하겠다.
메세지보내기
ChatActivity.java
package com.example.ex15;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.Gravity;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.database.ChildEventListener;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import org.w3c.dom.Text;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
public class ChatActivity extends AppCompatActivity {
FirebaseUser user;
FirebaseDatabase db;
DatabaseReference ref;
EditText contents;
ArrayList<MemoVO> array = new ArrayList<>();
ChatAdapter chatAdapter= new ChatAdapter();
RecyclerView list;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chat);
user = FirebaseAuth.getInstance().getCurrentUser();
getSupportActionBar().setTitle("채팅 |" +user.getEmail());
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
db=FirebaseDatabase.getInstance();
//채팅목록
ref=db.getReference("chats");
ref.addChildEventListener(new ChildEventListener() {
@Override
public void onChildAdded(@NonNull DataSnapshot snapshot, @Nullable String previousChildName) {
MemoVO vo = (MemoVO)snapshot.getValue(MemoVO.class);
array.add(vo);
System.out.println(vo.toString());
chatAdapter.notifyDataSetChanged();
list.scrollToPosition(array.size()-1);
}
@Override
public void onChildChanged(@NonNull DataSnapshot snapshot, @Nullable String previousChildName) {
}
@Override
public void onChildRemoved(@NonNull DataSnapshot snapshot) {
chatAdapter.notifyDataSetChanged();
}
@Override
public void onChildMoved(@NonNull DataSnapshot snapshot, @Nullable String previousChildName) {
}
@Override
public void onCancelled(@NonNull DatabaseError error) {
}
});
contents = findViewById(R.id.contents);
list = findViewById(R.id.list);
list.setAdapter(chatAdapter);
list.setLayoutManager(new LinearLayoutManager(this));
ImageView send = findViewById(R.id.send);
//전송버튼을 클릭한경우
send.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String strContents= contents.getText().toString();
if(strContents.equals("")){
Toast.makeText(ChatActivity.this, "전송할 내용을 입력하세요!", Toast.LENGTH_SHORT).show();
}else{
//전송
MemoVO vo = new MemoVO();
vo.setEmail(user.getEmail());
SimpleDateFormat sdf= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
vo.setDate(sdf.format(new Date()));
vo.setContents(strContents);
ref=db.getReference("chats").push();
vo.setKey(ref.getKey());
ref.setValue(vo);
contents.setText("");
}
}
});
}
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
switch(item.getItemId()){
case android.R.id.home:
finish();
break;
}
return super.onOptionsItemSelected(item);
}
//채팅 어댑터
class ChatAdapter extends RecyclerView.Adapter<ChatAdapter.ViewHolder>{
@NonNull
@Override
public ChatAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = getLayoutInflater().inflate(R.layout.item_chat,parent,false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ChatAdapter.ViewHolder holder, int position) {
MemoVO vo = array.get(position);
holder.contents.setText(vo.getContents());
holder.email.setText(vo.getEmail());
holder.date.setText(vo.getDate());
LinearLayout.LayoutParams paramsContents =
(LinearLayout.LayoutParams) holder.contents.getLayoutParams();
LinearLayout.LayoutParams paramsDate =
(LinearLayout.LayoutParams) holder.date.getLayoutParams();
if (vo.getEmail().equals(user.getEmail())) {//내가보낸메세지
paramsContents.gravity = Gravity.RIGHT;
paramsDate.gravity = Gravity.RIGHT;
holder.email.setVisibility(View.GONE);
holder.contents.setBackgroundResource(R.drawable.bubble);
//내가보낸 메세지에서 롱클릭한 경우
holder.contents.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
AlertDialog.Builder box = new AlertDialog.Builder(ChatActivity.this);
box.setTitle("메뉴를 선택하세요!");
box.setItems(new String[]{"삭제", "취소"}, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if(which==0){
//삭제
ref=db.getReference("chats").child(vo.getKey());
ref.removeValue();
}
}
});
box.show();
return false;
}
});
} else {//다른사람메세지
paramsContents.gravity = Gravity.LEFT;
paramsDate.gravity = Gravity.LEFT;
holder.contents.setBackgroundResource(R.drawable.left_bubble);
holder.email.setVisibility(View.VISIBLE);
}
}
@Override
public int getItemCount() {
return array.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
TextView contents,date,email;
public ViewHolder(@NonNull View itemView) {
super(itemView);
contents=itemView.findViewById(R.id.contents);
date=itemView.findViewById(R.id.date);
email=itemView.findViewById(R.id.email);
}
}
}
}
activity_chat.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ChatActivity"
android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="0sp"
android:layout_weight="1"/>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="@+id/contents"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10sp"
android:hint="내용입력"/>
<ImageView
android:id="@+id/send"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_send"
android:layout_alignParentRight="true"
android:layout_margin="10sp"/>
</RelativeLayout>
</LinearLayout>
item_chat.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_margin="10sp">
<TextView
android:id="@+id/contents"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="여기에는 글 내용이 출력됩니다."
android:background="@drawable/bubble"
android:padding="10sp"
android:fontFamily="@font/kang"/>
<TextView
android:id="@+id/date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="여기에는 글쓴 날짜"
android:fontFamily="@font/kang"/>
<TextView
android:id="@+id/email"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="누가 썼나요 ?"
android:fontFamily="@font/ho"
android:textSize="10sp"/>
</LinearLayout>
-> 레이아웃 아이디를 잘줘야한다. 메세지를 꾹누르게되면 삭제,취소버튼이 나오는데 아직 구현되지는 않았다.
- drawable에 오른쪽 왼쪽 버블을 줘서 디자인을 다르게했다. 디자인 참고는 여기 : https://ichi.pro/ko/android-chat-bubbles-android-eseo-ios-seutail-chaeting-bildeu-142487010469521 그대로 퍼와서 적용했다.
에뮬레이터 두개로 대화를 시도해보려다가 속터져죽을뻔했다. 내컴에선 무리인걸로.. 끝!
댓글남기기