1. 인증 (Authentication)
Firebase에서는 기본으로 제공하는 비밀번호 또는 전화번호를 통한 인증 기능 뿐만 아니라 구글, 페이스북, 트위터 등과 같은 타 사이트 인증 기능도 제공합니다.
1) Firebase - Authentication에서 [시작하기] 버튼을 클릭합니다.
2) Sign-in-method에서 Firebase에서 제공하는 다양한 인증 방법 중 원하는 것을 선택할 수 있습니다.
3) 이메일/비밀번호를 선택했다면, 해당 화면에서 사용 설정을 ON으로 설정합니다.
4) [저장] 버튼을 누르면 다음과 같이 이메일/비밀번호 사용 설정이 완료됩니다.
5) Authentication을 사용하기 위해서 build.gradle에 해당 라이브러리를 추가합니다.
implementation 'com.google.firebase:firebase-auth-ktx'
6) 안드로이드 코드에서 FirebaseAuth 객체를 선언 및 초기화 합니다.
// FirebaseAuth 객체 선언
private lateinit var auth: FirebaseAuth
// auth 객체 초기화
auth = Firebase.auth
7) 회원가입과 로그인 기능을 구현합니다.
Firebase는 사용자가 입력한 이메일이 서버 DB에 있는지 확인합니다.
- DB에 있는 이메일 : 비밀번호를 대조하여 올바르다면 로그인 처리합니다.
- DB에 없는 이메일 : 새롭게 계정을 등록하고 로그인 처리합니다.
// 회원가입 기능
auth.createUserWithEmailAndPassword(email, password)
.addOnCompleteListener(this) { task ->
if (task.isSuccessful) {
// 회원가입 성공
} else {
// 회원가입 실패
}
}
// 로그인 기능
auth.signInWithEmailAndPassword(email, password)
.addOnCompleteListener(this) { task ->
val currentUser = Firebase.auth.currentUser // 로그인 유무 확인
if (task.isSuccessful && currentUser != null) {
// 로그인 성공
} else {
// 로그인 실패
}
}
2. 실시간 데이터베이스 (Realtime Database)
Firebase의 Realtime Database는 NoSQL 기반 Cloud-Hosted Database이기 때문에 실시간으로 모든 클라이언트에서 데이터가 동기화되어 사용할 수 있습니다.
1) Firebase - Realtime Database에서 [데이터베이스 만들기] 버튼을 클릭합니다.
2) 데이터베이스 설정 창이 표시되는데 먼저 실시간 데이터베이스 위치를 설정합니다.
대한민국이 없으므로 default인 미국을 선택합니다.
3) 그 다음 보안 규칙을 설정해야 하는데 테스트 모드에서 시작을 선택합니다.
- 잠금 모드 : 데이터는 기본적으로 비공개되며, 인증된 사용자만 읽기/쓰기가 가능
- 테스트 모드 : 데이터가 기본적으로 공개되며, 참조 사용자는 누구나 읽기/쓰기가 가능
4) 모든 설정이 끝났다면 데이터베이스가 생성됩니다.
5) 추가적으로 인증된 사용자만 데이터베이스에 접근 가능하도록 다음과 같이 규칙을 설정합니다.
6) Realtime Database를 사용하기 위해서 build.gradle에 해당 라이브러리를 추가합니다.
implementation 'com.google.firebase:firebase-database-ktx'
7) 안드로이드 코드에서 DatabaseReference 객체를 선언 및 초기화 합니다.
// DatabaseReference 객체 선언
private lateinit var database: DatabaseReference
// database 객체 초기화
database = Firebase.database.reference
8) 데이터베이스에서의 데이터 쓰기/읽기 기능을 구현합니다.
- 데이터 쓰기 : setValue()를 통해 지정한 위치에 데이터 저장 또는 기존 데이터 대체
- 데이터 읽기
- 영구 리스너 : ValueEventListener에서 getValue()를 통해 지정한 위치에 있는 데이터 불러오기
- 일회성 : get()을 사용하여 데이터 한번에 불러오기
// 데이터 쓰기
database.child("Users").child("username").push().apply {
setValue("John")
}
// 데이터 읽기
database.child("Users").child("username").get()
.addOnSuccessListener {
val myUserItem = it.getValue(UserItem::class.java)
myUserName = myUserItem?.username ?: ""
}
// 영구 리스너로 데이터 읽기
database.child("Users").child("username")
.addValueEventListener(object : ValueEventListener {
override fun onDataChange(snapshot: DataSnapshot) {
val myUserItem = snapshot.getValue(UserItem::class.java)
myUserName = myUserItem?.username ?: ""
}
override fun onCancelled(error: DatabaseError) {
Log.w(TAG, "Error : ", error.toException())
}
})
9) 데이터베이스에서의 데이터 업데이트/삭제 기능을 구현합니다.
- 데이터 업데이트 : updateChildren()을 통해 특정 하위 노드에 있는 데이터 업데이트
- 데이터 삭제 : removeValue()를 통해 지정한 위치에 있는 데이터 삭제
// 데이터 업데이트
val message = binding.etMessage.text.toString()
val updates: MutableMap<String, Any> = hashMapOf(
"Chats/$myUserId/$otherUserId/lastMessage" to message,
"Chats/$otherUserId/$myUserId/lastMessage" to message
)
database.updateChildren(updates)
// 데이터 삭제
database.child("Users").child("username").removeValue()
10) 데이터베이스의 데이터 목록 다루기 기능을 추가합니다.
push()를 통해 목록에 데이터를 추가할 수 있습니다.
목록을 사용할 경우에는 ChildEventListener를 연결하여 하위 이벤트를 수신 대기해야 합니다.
// 하위 요소가 추가 또는 업데이트 되었을 경우, 하위 이벤트 수신 대기
database.child("Users").child("username")
.addChildEventListener(object : ChildEventListener {
// 항목 목록을 검색하거나 항목 목록에 대한 추가를 수신 대기
override fun onChildAdded(snapshot: DataSnapshot, previousChildName: String?) {}
// 목록의 항목에 대한 변경사항을 수신 대기
override fun onChildChanged(snapshot: DataSnapshot, previousChildName: String?) {}
// 목록의 항목 삭제를 수신 대기
override fun onChildRemoved(snapshot: DataSnapshot) {}
// 순서가 지정된 목록의 항목 순서 변경사항을 수신 대기
override fun onChildMoved(snapshot: DataSnapshot, previousChildName: String?) {}
override fun onCancelled(error: DatabaseError) {}
})
3. 클라우드 메세징 (Cloud Messaging)
Firebase Cloud Messaging(FCM)은 구글 클라우드 서버를 사용해 앱에서 서버에 연결하지 않아도 기기의 내부 연결을 통해 메시지를 보낼 수 있습니다.
1) Firebase - 프로젝트 개요 - 프로젝트 설정 - 클라우드 메시징에서 Cloud Messaging API를 선택합니다.
2) Cloud Messaging을 사용 설정 하면, 서버 키가 발급됩니다.
3) Cloud Messaging을 사용하기 위해서 build.gradle에 해당 라이브러리를 추가합니다.
implementation 'com.google.firebase:firebase-messaging-ktx'
4) Manifest에 FirebaseMessagingService를 확장하는 서비스와 해당 서비스의 알림 채널을 추가합니다.
- 백그라운드에서 앱의 알림을 수신하는 것 외에 다른 방식으로 메시지를 처리하려는 경우에 필요
- 포그라운드 앱의 알림 수신, 데이터 페이로드 수신, 업스트림 메시지 전송 등
<!-- 서비스 설정 -->
<service
android:name=".service.MyFirebaseMessagingService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<!-- 알림 채널 설정 -->
<meta-data
android:name="com.google.firebase.messaging.default_notification_channel_id"
android:value="@string/default_notification_channel_id" />
5) 안드로이드 코드에서 런타임 알림 권한을 요청합니다.
사용자가 POST_NOTIFICATIONS 권한을 부여할 때까지 앱에서 알림을 표시할 수 없습니다.
private val requestPermissionLauncher = registerForActivityResult(
ActivityResultContracts.RequestPermission()
) { isGranted: Boolean ->
if (isGranted) {
// FCM SDK (and your app) can post notifications.
} else {
// 알림 권한 없음
}
}
private fun askNotificationPermission() {
// This is only necessary for API level >= 33 (TIRAMISU)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) ==
PackageManager.PERMISSION_GRANTED
) {
// FCM SDK (and your app) can post notifications.
} else if (shouldShowRequestPermissionRationale(Manifest.permission.POST_NOTIFICATIONS)) {
showPermissionRationalDialog()
} else {
requestPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS)
}
}
}
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
private fun showPermissionRationalDialog() {
AlertDialog.Builder(this)
.setMessage("알림 권한이 없으면 알림을 받을 수 없습니다.")
.setPositiveButton("권한 허용하기") { _, _ ->
requestPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS)
}
.setNegativeButton("취소") { dialogInterface, _ ->
dialogInterface.cancel()
}
.show()
}
6) FCM 기능을 위한 MyFirebaseMessagingService 코드를 작성합니다.
class MyFirebaseMessagingService : FirebaseMessagingService() {
// 메시지 수신
override fun onMessageReceived(message: RemoteMessage) {
super.onMessageReceived(message)
val name = "채팅 알림"
val descriptionText = "채팅 알림입니다."
val importance = NotificationManager.IMPORTANCE_DEFAULT
val mChannel = NotificationChannel(
getString(R.string.default_notification_channel_id),
name,
importance
)
mChannel.description = descriptionText
val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
notificationManager.createNotificationChannel(mChannel)
val body = message.notification?.body ?: ""
val notificationBuilder = NotificationCompat.Builder(
applicationContext,
getString(R.string.default_notification_channel_id)
)
.setSmallIcon(R.drawable.ic_baseline_chat_24)
.setContentTitle(getString(R.string.app_name))
.setContentText(body)
NotificationManagerCompat.from(applicationContext).notify(0, notificationBuilder.build())
}
// 새 토큰이 생성될 때마다 호출됨
override fun onNewToken(token: String) {
super.onNewToken(token)
}
}
7) FCM 메시지 보내기 기능을 추가합니다.
val notification = JSONObject()
notification.put("title", getString(R.string.app_name))
notification.put("body", message)
val root = JSONObject()
root.put("to", otherUserFcmToken)
root.put("priority", "high")
root.put("notification", notification)
val requestBody = root.toString()
.toRequestBody("application/json; charset=utf-8".toMediaType())
val request = Request.Builder().post(requestBody)
.url("https://fcm.googleapis.com/fcm/send")
.header("Authorization", "key=${getString(R.string.FCM_SERVER_KEY)}").build()
val client = OkHttpClient()
client.newCall(request).enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
e.stackTraceToString()
}
override fun onResponse(call: Call, response: Response) {
// ignore onResponse()
}
})
8) FCM 토큰 가져오기 기능을 추가합니다.
Firebase.messaging.token.addOnCompleteListener(OnCompleteListener { task ->
if (!task.isSuccessful) {
Log.w(TAG, "Fetching FCM registration token failed", task.exception)
return@OnCompleteListener
}
// Get new FCM registration token
val token = task.result
})
'안드로이드 > 활용' 카테고리의 다른 글
[Android] 앱 위젯 만들기 (0) | 2023.09.12 |
---|---|
[Android] 현재 위치 정보 가져오기 (0) | 2023.09.08 |
[Android] Firebase (0) | 2023.08.29 |
[Android] Lottie 사용하기 (0) | 2023.08.22 |
[Android] Glide 사용하기 (0) | 2023.08.22 |