Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[TNT-187] FCM 기본 세팅 #111

Merged
merged 4 commits into from
Feb 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/workflows/android-ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ jobs:
echo DEBUG_BASE_API_URL=\"${{ secrets.DEBUG_BASE_API_URL }}\" >> ./local.properties
echo KAKAO_NATIVE_APP_KEY=${{ secrets.KAKAO_NATIVE_APP_KEY }} >> ./local.properties

- name: add google-services.json
run: |
echo '${{ secrets.GOOGLE_SERVICES_JSON }}' > ./app/src/google-services.json

- name: Grant execute permission for gradlew
run: chmod +x gradlew

Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -175,3 +175,4 @@ fabric.properties
!/gradle/wrapper/gradle-wrapper.jar

# End of https://www.toptal.com/developers/gitignore/api/androidstudio,android
app/google-services.json
5 changes: 5 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ plugins {
id("tnt.android.application")
id("tnt.android.compose")
id("com.google.android.gms.oss-licenses-plugin")
id("com.google.gms.google-services")
}

android {
Expand Down Expand Up @@ -61,4 +62,8 @@ dependencies {
implementation(libs.androidx.activity.compose)
implementation(libs.kakao.user)
implementation(libs.play.services.oss.licenses)

implementation(platform(libs.firebase.bom))
implementation(libs.firebase.messaging)
implementation(libs.firebase.analytics)
}
8 changes: 8 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,14 @@
<activity
android:name="com.google.android.gms.oss.licenses.OssLicensesActivity"
android:theme="@style/Theme.AppCompat.NoActionBar" />

<service
android:name=".service.MessagingService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
</application>

</manifest>
19 changes: 19 additions & 0 deletions app/src/main/java/co/kr/tnt/service/MessagingService.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package co.kr.tnt.service

import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.RemoteMessage
import dagger.hilt.android.AndroidEntryPoint

@AndroidEntryPoint
class MessagingService : FirebaseMessagingService() {

override fun onMessageReceived(message: RemoteMessage) {
super.onMessageReceived(message)
// TODO
}

override fun onNewToken(token: String) {
super.onNewToken(token)
// TODO
}
}
2 changes: 2 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,6 @@ plugins {
alias(libs.plugins.ksp) apply false
alias(libs.plugins.detekt) apply false
alias(libs.plugins.ktlint)
alias(libs.plugins.google.services) apply false
alias(libs.plugins.firebase.crashlytics) apply false
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@ package co.kr.data.network.model
import co.kr.tnt.domain.model.AuthType
import kotlinx.serialization.Serializable

// TODO fcm token
@Serializable
data class LoginRequest(
val socialType: AuthType,
val fcmToken: String = "EMPTY",
val fcmToken: String,
val socialAccessToken: String,
)
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,13 @@ internal class LoginRepositoryImpl @Inject constructor(

override suspend fun login(
authType: AuthType,
messagingToken: String,
accessToken: String,
): LoginResult {
val response = loginRemoteDataSource.postLogin(
loginRequest = LoginRequest(
socialType = authType,
fcmToken = messagingToken,
socialAccessToken = accessToken,
),
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ interface LoginRepository {

suspend fun login(
authType: AuthType,
messagingToken: String,
accessToken: String,
): LoginResult

Expand Down
3 changes: 3 additions & 0 deletions feature/login/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,7 @@ android {

dependencies {
implementation(projects.core.login)

implementation(platform(libs.firebase.bom))
implementation(libs.firebase.messaging)
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ internal class LoginContract {
data class OnCheckTerm(val termState: TermState) : LoginUiEvent
data class OnClickTermLink(val link: String) : LoginUiEvent
data object OnClickNext : LoginUiEvent
data class OnGetMessagingTokenSucceed(val token: String) : LoginUiEvent
}

sealed interface LoginSideEffect : UiSideEffect {
Expand Down
9 changes: 9 additions & 0 deletions feature/login/src/main/java/co/kr/tnt/login/LoginScreen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import androidx.compose.material3.Text
import androidx.compose.material3.rememberModalBottomSheetState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
Expand Down Expand Up @@ -54,6 +55,8 @@ import co.kr.tnt.login.LoginContract.LoginUiEvent
import co.kr.tnt.login.LoginContract.LoginUiState
import co.kr.tnt.login.kakao.KakaoLoginSdk
import co.kr.tnt.login.model.TermState
import com.google.firebase.Firebase
import com.google.firebase.messaging.messaging
import kotlinx.coroutines.launch

@OptIn(ExperimentalMaterial3Api::class)
Expand Down Expand Up @@ -139,6 +142,12 @@ internal fun LoginRoute(
}
}
}

SideEffect {
Firebase.messaging.token.addOnCompleteListener {
viewModel.setEvent(LoginUiEvent.OnGetMessagingTokenSucceed(token = it.result ?: ""))
}
}
}

@Composable
Expand Down
3 changes: 3 additions & 0 deletions feature/login/src/main/java/co/kr/tnt/login/LoginViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ internal class LoginViewModel @Inject constructor(
LoginUiState(),
) {
private var loginResult: LoginResult? = null
private var messagingToken: String = ""

override suspend fun handleEvent(event: LoginUiEvent) {
when (event) {
Expand All @@ -39,6 +40,7 @@ internal class LoginViewModel @Inject constructor(
}

LoginUiEvent.OnClickNext -> navigateToSignup()
is LoginUiEvent.OnGetMessagingTokenSucceed -> messagingToken = event.token
}
}

Expand All @@ -51,6 +53,7 @@ internal class LoginViewModel @Inject constructor(
loginRepository.login(
authType = authType,
accessToken = accessToken,
messagingToken = messagingToken,
)
}.onSuccess { loginResult ->
loginResult.userType?.let { userType ->
Expand Down
1 change: 1 addition & 0 deletions feature/main/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ dependencies {
implementation(libs.kotlinx.immutable)
implementation(libs.androidx.core.splashscreen)
implementation(libs.accompanist.permissions)
implementation(libs.firebase.messaging)
androidTestImplementation(libs.hilt.android.testing)
kspAndroidTest(libs.hilt.android.compiler)
}
28 changes: 28 additions & 0 deletions feature/main/src/main/java/co/kr/tnt/main/MainActivity.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package co.kr.tnt.main

import android.os.Bundle
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
Expand All @@ -18,6 +19,7 @@ import co.kr.tnt.main.ui.rememberTnTAppState
import co.kr.tnt.ui.permission.TnTPermission
import com.google.accompanist.permissions.ExperimentalPermissionsApi
import com.google.accompanist.permissions.rememberMultiplePermissionsState
import com.google.firebase.messaging.FirebaseMessaging
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject

Expand All @@ -33,6 +35,7 @@ class MainActivity : ComponentActivity() {
super.onCreate(savedInstanceState)
enableEdgeToEdge()

getMessagingToken()
splashScreen.setKeepOnScreenCondition { viewModel.uiState.value.showSplash }

setContent {
Expand All @@ -50,6 +53,16 @@ class MainActivity : ComponentActivity() {
}

CheckPermissionEffect()

LaunchedEffect(viewModel.effect) {
viewModel.effect.collect { effect ->
when (effect) {
is MainContract.MainSideEffect.ShowToast -> {
Toast.makeText(this@MainActivity, effect.message, Toast.LENGTH_SHORT).show()
}
}
}
}
}
}

Expand All @@ -68,4 +81,19 @@ class MainActivity : ComponentActivity() {
}
}
}

// TODO API 변경 시 제거 예정 코드
private fun getMessagingToken() {
FirebaseMessaging
.getInstance()
.token
.addOnSuccessListener { token ->
token?.let {
viewModel.setEvent(MainUiEvent.OnGetMessagingTokenSucceeded(token))
} ?: viewModel.setEvent(MainUiEvent.OnGetMessagingTokenFailed)
}
.addOnFailureListener {
viewModel.setEvent(MainUiEvent.OnGetMessagingTokenFailed)
}
}
}
6 changes: 5 additions & 1 deletion feature/main/src/main/java/co/kr/tnt/main/MainContract.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@ internal class MainContract {

sealed class MainUiEvent : UiEvent {
data object OnNotificationPermissionRevoked : MainUiEvent()
data class OnGetMessagingTokenSucceeded(val token: String) : MainUiEvent()
data object OnGetMessagingTokenFailed : MainUiEvent()
}

data object MainSideEffect : UiSideEffect
sealed interface MainSideEffect : UiSideEffect {
data class ShowToast(val message: String) : MainSideEffect
}
}
32 changes: 18 additions & 14 deletions feature/main/src/main/java/co/kr/tnt/main/MainViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,25 @@ internal class MainViewModel @Inject constructor(
private val settingRepository: SettingRepository,
) :
BaseViewModel<MainUiState, MainUiEvent, MainSideEffect>(MainUiState()) {
init {
viewModelScope.launch {
val startDestination = getStartDestination()
override suspend fun handleEvent(event: MainUiEvent) {
when (event) {
MainUiEvent.OnNotificationPermissionRevoked -> settingRepository.setEnablePushNotification(false)
is MainUiEvent.OnGetMessagingTokenSucceeded -> {
viewModelScope.launch {
val startDestination = getStartDestination()

updateState {
copy(
showSplash = false,
startDestination = startDestination,
)
}
}
}

updateState {
copy(
showSplash = false,
startDestination = startDestination,
)
// TODO API 변경 시 제거 예정 코드
MainUiEvent.OnGetMessagingTokenFailed -> {
sendEffect(MainSideEffect.ShowToast("네트워크 환경을 확인하신 후 앱을 재실행해주세요."))
}
}
}
Expand All @@ -47,10 +57,4 @@ internal class MainViewModel @Inject constructor(
},
)
}

override suspend fun handleEvent(event: MainUiEvent) {
when (event) {
MainUiEvent.OnNotificationPermissionRevoked -> settingRepository.setEnablePushNotification(false)
}
}
}
11 changes: 11 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ coroutine = "1.9.0"
hilt = "2.51.1"
hiltNavigationCompose = "1.2.0"

## firebase
googleServices = "4.4.2"
firebaseBom = "33.9.0"
crashlytics = "3.0.3"

## Test
junit = "4.13.2"
junitJupiter = "5.11.4"
Expand Down Expand Up @@ -129,6 +134,10 @@ detekt-plugin = { module = "io.gitlab.arturbosch.detekt:detekt-gradle-plugin", v
ktlint-plugin = { module = "org.jlleitschuh.gradle:ktlint-gradle", version.ref = "ktlint" }
oss-licenses-plugin = { module = "com.google.android.gms:oss-licenses-plugin", version.ref = "ossLicensesPlugin" }

firebase-bom = { module = "com.google.firebase:firebase-bom", version.ref = "firebaseBom" }
firebase-analytics = { module = "com.google.firebase:firebase-analytics" }
firebase-messaging = { module = "com.google.firebase:firebase-messaging" }

[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
Expand All @@ -140,3 +149,5 @@ ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
hilt = { id = "com.google.dagger.hilt.android", version.ref = "hilt" }
detekt = { id = "io.gitlab.arturbosch.detekt", version.ref = "detekt" }
ktlint = { id = "org.jlleitschuh.gradle.ktlint", version.ref = "ktlint" }
google-services = { id = "com.google.gms.google-services", version.ref = "googleServices" }
firebase-crashlytics = { id = "com.google.firebase.crashlytics", version.ref = "crashlytics" }