Skip to content

Commit

Permalink
알림 fcm 서비스 추가 및 토큰 업데이트 기능 추가
Browse files Browse the repository at this point in the history
  • Loading branch information
kts6056 committed Sep 10, 2024
1 parent dda0ac6 commit 7fae57e
Show file tree
Hide file tree
Showing 17 changed files with 146 additions and 10 deletions.
2 changes: 1 addition & 1 deletion app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ dependencies {
implementation(project(":presentation:home"))
implementation(project(":presentation:step"))
implementation(project(":presentation:checklist"))

implementation(project(":presentation:notification"))

implementation(libs.androidx.startup)
}
1 change: 1 addition & 0 deletions data/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,5 @@ dependencies {
implementation(platform(libs.firebase.bom))
implementation(libs.firebase.auth)
implementation(libs.firebase.crashlytics)
implementation(libs.firebase.messaging.ktx)
}
18 changes: 18 additions & 0 deletions data/src/main/java/com/dkin/chevit/data/di/FirebaseModule.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.dkin.chevit.data.di

import com.google.firebase.messaging.FirebaseMessaging
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton

@Module
@InstallIn(SingletonComponent::class)
class FirebaseModule {
@Singleton
@Provides
fun provideFirebaseMessage(): FirebaseMessaging {
return FirebaseMessaging.getInstance()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ import com.dkin.chevit.domain.usecase.auth.WithDrawUserUseCase
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.components.ViewModelComponent
import dagger.hilt.components.SingletonComponent

@Module
@InstallIn(ViewModelComponent::class)
@InstallIn(SingletonComponent::class)
internal object AuthUseCaseModule {
@Provides
fun provideGetUserStateUseCase(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,17 @@ import com.dkin.chevit.domain.repository.AuthRepository
import com.dkin.chevit.domain.repository.NotificationRepository
import com.dkin.chevit.domain.usecase.notification.GetNotificationInBoxItemUseCase
import com.dkin.chevit.domain.usecase.notification.GetNotificationSettingUseCase
import com.dkin.chevit.domain.usecase.notification.SyncFirebaseMessageTokenUseCase
import com.dkin.chevit.domain.usecase.notification.UpdateNotificationEnableStateUseCase
import com.dkin.chevit.domain.usecase.notification.UpdatePushTokenUseCase
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.components.ViewModelComponent
import dagger.hilt.components.SingletonComponent

@Module
@InstallIn(ViewModelComponent::class)
@InstallIn(SingletonComponent::class)
internal object NotificationUseCaseModule {
@Provides
fun provideGetNotificationSettingUseCase(
Expand All @@ -24,6 +26,17 @@ internal object NotificationUseCaseModule {
authRepository
)

@Provides
fun provideSyncFirebaseMessageTokenUseCase(
coroutineDispatcherProvider: CoroutineDispatcherProvider,
notificationRepository: NotificationRepository,
updatePushTokenUseCase: UpdatePushTokenUseCase
) = SyncFirebaseMessageTokenUseCase(
coroutineDispatcherProvider,
notificationRepository,
updatePushTokenUseCase
)

@Provides
fun provideUpdatePushTokenUseCase(
coroutineDispatcherProvider: CoroutineDispatcherProvider,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ import com.dkin.chevit.domain.usecase.plan.UpdateTemplateUseCase
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.components.ViewModelComponent
import dagger.hilt.components.SingletonComponent

@Module
@InstallIn(ViewModelComponent::class)
@InstallIn(SingletonComponent::class)
internal object PlanUseCaseModule {
@Provides
fun provideCopyTemplateUseCase(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ import com.dkin.chevit.domain.usecase.service.GetAppInfoUseCase
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.components.ViewModelComponent
import dagger.hilt.components.SingletonComponent

@Module
@InstallIn(ViewModelComponent::class)
@InstallIn(SingletonComponent::class)
internal object ServiceUseCaseModule {
@Provides
fun provideGetAppInfoUseCase(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,19 @@ import com.dkin.chevit.domain.base.None
import com.dkin.chevit.domain.model.Notification
import com.dkin.chevit.domain.model.NotificationSetting
import com.dkin.chevit.domain.repository.NotificationRepository
import com.google.firebase.messaging.FirebaseMessaging
import kotlinx.coroutines.tasks.await
import kotlinx.coroutines.withTimeout
import javax.inject.Inject

internal class NotificationRepositoryImpl @Inject constructor(
private val notificationAPI: NotificationAPI
private val notificationAPI: NotificationAPI,
private val firebaseMessaging: FirebaseMessaging
) : NotificationRepository {
override suspend fun getPushToken(): String {
return runCatching { firebaseMessaging.token.await() }.getOrDefault("")
}

override suspend fun updatePushToken(token: String): None {
val payload = NotificationSettingUpdatePayload(pushToken = token)
notificationAPI.updatePushToken(body = payload)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import com.dkin.chevit.domain.model.Notification
import com.dkin.chevit.domain.model.NotificationSetting

interface NotificationRepository {
suspend fun getPushToken(): String
suspend fun updatePushToken(token: String): None
suspend fun updateNotificationPushEnabled(notificationEnabled: Boolean): NotificationSetting
suspend fun fetchNotificationList(): DomainListModel<Notification>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.dkin.chevit.domain.usecase.notification

import com.dkin.chevit.domain.base.CoroutineDispatcherProvider
import com.dkin.chevit.domain.base.IOUseCase
import com.dkin.chevit.domain.base.None
import com.dkin.chevit.domain.repository.NotificationRepository

class SyncFirebaseMessageTokenUseCase(
coroutineDispatcherProvider: CoroutineDispatcherProvider,
private val notificationRepository: NotificationRepository,
private val updatePushTokenUseCase: UpdatePushTokenUseCase
) : IOUseCase<Unit, None>(coroutineDispatcherProvider) {
override suspend fun execute(params: Unit): None {
val pushToken = notificationRepository.getPushToken()
val param = UpdatePushTokenUseCase.Param(pushToken)
updatePushTokenUseCase(param)
return None
}
}
6 changes: 5 additions & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ material = "1.12.0"
protobuf-plugin = "0.9.4"
protobuf = "3.25.1"
browser = "1.8.0"
lifecycleProcess = "2.8.5"

# Firebase
google-services = "4.4.2"
Expand All @@ -31,6 +32,7 @@ firebase-bom = "33.2.0"

# Compose
compose-bom = "2024.09.00"
compose-hilt-navigation = "1.2.0"

# DI
hilt = "2.52"
Expand Down Expand Up @@ -74,6 +76,7 @@ androidx-startup = { module = "androidx.startup:startup-runtime", version.ref =
androidx-material = { group = "com.google.android.material", name = "material", version.ref = "material" }
androidx-datastore = { module = "androidx.datastore:datastore", version.ref = "data-store" }
androidx-browser = { module = "androidx.browser:browser", version.ref = "browser" }
androidx-lifecycle-process = { group = "androidx.lifecycle", name = "lifecycle-process", version.ref = "lifecycleProcess" }

#Compose
compose-bom = { module = "androidx.compose:compose-bom", version.ref = "compose-bom" }
Expand All @@ -87,7 +90,7 @@ compose-uiToolingPreview = { group = "androidx.compose.ui", name = "ui-tooling-p
compose-test-uiManifest = { group = "androidx.compose.ui", name = "ui-test-manifest" }
compose-test-ui = { group = "androidx.compose.ui", name = "ui-test-junit4" }
compose-viewModel = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-compose", version.ref = "lifecycle" }
compose-hiltViewModel = { group = "androidx.hilt", name = "hilt-navigation-compose", version = "1.2.0" }
compose-hiltViewModel = { group = "androidx.hilt", name = "hilt-navigation-compose", version = "compose-hilt-navigation" }

# Firebase
firebase-bom = { module = "com.google.firebase:firebase-bom", version.ref = "firebase-bom" }
Expand All @@ -96,6 +99,7 @@ firebase-messaging = { module = "com.google.firebase:firebase-messaging" }
firebase-crashlytics = { module = "com.google.firebase:firebase-crashlytics-ktx" }
firebase-performance = { module = "com.google.firebase:firebase-perf-ktx" }
firebase-auth = { module = "com.google.firebase:firebase-auth-ktx" }
firebase-messaging-ktx = { module = "com.google.firebase:firebase-messaging-ktx" }
playservices-auth = { module = "com.google.android.gms:play-services-auth", version.ref = "play-services-auth" }

#Navigation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.dkin.chevit.presentation.home
import com.dkin.chevit.core.mvi.MVIViewModel
import com.dkin.chevit.domain.base.getOrNull
import com.dkin.chevit.domain.usecase.auth.GetUserUseCase
import com.dkin.chevit.domain.usecase.notification.SyncFirebaseMessageTokenUseCase
import com.dkin.chevit.domain.usecase.plan.GetMyChecklistUseCase
import com.dkin.chevit.presentation.home.model.CheckListItem
import dagger.hilt.android.lifecycle.HiltViewModel
Expand All @@ -13,6 +14,7 @@ import javax.inject.Inject
class HomeViewModel @Inject constructor(
private val getMyChecklistUseCase: GetMyChecklistUseCase,
private val getUserUseCase: GetUserUseCase,
private val syncFirebaseMessageTokenUseCase: SyncFirebaseMessageTokenUseCase
) : MVIViewModel<HomeIntent, HomeState, HomeEffect>() {
private var nickname = ""

Expand All @@ -21,6 +23,7 @@ class HomeViewModel @Inject constructor(
override suspend fun processIntent(intent: HomeIntent) {
when (intent) {
HomeIntent.Initialize -> {
syncFirebaseMessageToken()
getHomeTabInfo()
}

Expand All @@ -36,6 +39,10 @@ class HomeViewModel @Inject constructor(
setEffect { HomeEffect.NavigateToCheckList(id) }
}

private suspend fun syncFirebaseMessageToken() {
syncFirebaseMessageTokenUseCase(Unit)
}

private suspend fun getHomeTabInfo() {
val userAsync = async { getUserUseCase(Unit) }
val checklistAsync = async { getMyChecklistUseCase(Unit) }
Expand Down
1 change: 1 addition & 0 deletions presentation/notification/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
19 changes: 19 additions & 0 deletions presentation/notification/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
plugins {
alias(libs.plugins.com.android.library)
alias(libs.plugins.org.jetbrains.kotlin.android)
}

apply(from = project.rootProject.file("gradle-scripts/base.gradle"))
apply(from = project.rootProject.file("gradle-scripts/hilt.gradle"))

android {
namespace = "com.dkin.chevit.presentation.notification"
}

dependencies {
implementation(project(":core"))
implementation(project(":domain"))

implementation(libs.firebase.messaging.ktx)
implementation(libs.androidx.lifecycle.process)
}
15 changes: 15 additions & 0 deletions presentation/notification/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

<application>
<service
android:name=".ChevitFirebaseMessagingService"
android:exported="false"
android:stopWithTask="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
</application>
</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.dkin.chevit.presentation.notification

import androidx.lifecycle.ProcessLifecycleOwner
import androidx.lifecycle.lifecycleScope
import com.dkin.chevit.domain.usecase.notification.UpdatePushTokenUseCase
import com.google.firebase.messaging.FirebaseMessagingService
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.launch
import timber.log.Timber
import javax.inject.Inject

@AndroidEntryPoint
class ChevitFirebaseMessagingService : FirebaseMessagingService() {
@Inject
lateinit var updatePushTokenUseCase: UpdatePushTokenUseCase

private val processLifecycleScope by lazy {
ProcessLifecycleOwner.get().lifecycleScope
}

override fun onNewToken(token: String) {
super.onNewToken(token)
Timber.d("onNewToken : $token")
processLifecycleScope.launch {
val param = UpdatePushTokenUseCase.Param(token)
updatePushTokenUseCase(param)
}
}
}
1 change: 1 addition & 0 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,4 @@ include(":presentation:splash")
include(":presentation:resource")
include(":presentation:step")
include(":presentation:checklist")
include(":presentation:notification")

0 comments on commit 7fae57e

Please sign in to comment.