diff --git a/app/build.gradle.kts b/app/build.gradle.kts index d1ab406f..76f37af5 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -4,10 +4,12 @@ plugins { alias(libs.plugins.android.application) alias(libs.plugins.kotlin.android) alias(libs.plugins.kotlin.serialization) + alias(libs.plugins.kotlin.compose) alias(libs.plugins.dagger.hilt) id("org.jetbrains.kotlin.kapt") alias(libs.plugins.navigationSafeArgs) - id("com.google.gms.google-services") + alias(libs.plugins.googleServices) + alias(libs.plugins.firebaseCrashlytics) } val properties = Properties().apply { @@ -77,7 +79,6 @@ android { kotlinOptions { jvmTarget = "11" } - composeOptions { kotlinCompilerExtensionVersion = "1.5.14" } } dependencies { @@ -163,7 +164,8 @@ dependencies { implementation(libs.accompanist.permissions) // Firebase - implementation(platform("com.google.firebase:firebase-bom:33.4.0")) - implementation("com.google.firebase:firebase-analytics-ktx") - implementation("com.google.firebase:firebase-config-ktx") + implementation(platform(libs.firebase.bom)) + implementation(libs.firebase.analytics.ktx) + implementation(libs.firebase.config.ktx) + implementation(libs.firebase.crashlytics) } \ No newline at end of file diff --git a/app/src/main/java/com/kuit/findu/analytics/AnalyticsEvent.kt b/app/src/main/java/com/kuit/findu/analytics/AnalyticsEvent.kt new file mode 100644 index 00000000..bd63666a --- /dev/null +++ b/app/src/main/java/com/kuit/findu/analytics/AnalyticsEvent.kt @@ -0,0 +1,16 @@ +package com.kuit.findu.analytics + +data class AnalyticsEvent( + val type: String, + val extras: List = emptyList(), +) { + data class Param( + val key: String, + val value: String, + ) + + companion object { + const val SCREEN_VIEW = "screen_view" // TYPE + const val SCREEN_NAME = "screen_name" // EXTRA_KEY + } +} \ No newline at end of file diff --git a/app/src/main/java/com/kuit/findu/analytics/AnalyticsExt.kt b/app/src/main/java/com/kuit/findu/analytics/AnalyticsExt.kt new file mode 100644 index 00000000..5c03728f --- /dev/null +++ b/app/src/main/java/com/kuit/findu/analytics/AnalyticsExt.kt @@ -0,0 +1,36 @@ +package com.kuit.findu.analytics + +fun AnalyticsHelper.logScreenView(screenName: String) { + logEvent( + AnalyticsEvent( + type = AnalyticsEvent.SCREEN_VIEW, + extras = listOf( + AnalyticsEvent.Param(AnalyticsEvent.SCREEN_NAME, screenName), + ), + ), + ) +} + +fun AnalyticsHelper.logUserSignIn(userName: String, type: String) { + logEvent( + AnalyticsEvent( + type = "signed_in", + extras = listOf( + AnalyticsEvent.Param("user_name", userName), + AnalyticsEvent.Param("login_type", type), + ), + ), + ) +} + +fun AnalyticsHelper.logUserSignUp(userName: String) { + logEvent( + AnalyticsEvent( + type = "signed_in", + extras = listOf( + AnalyticsEvent.Param("user_name", userName), + AnalyticsEvent.Param("login_type", "Kakao"), + ), + ), + ) +} diff --git a/app/src/main/java/com/kuit/findu/analytics/AnalyticsHelper.kt b/app/src/main/java/com/kuit/findu/analytics/AnalyticsHelper.kt new file mode 100644 index 00000000..69716ff2 --- /dev/null +++ b/app/src/main/java/com/kuit/findu/analytics/AnalyticsHelper.kt @@ -0,0 +1,5 @@ +package com.kuit.findu.analytics + +interface AnalyticsHelper { + fun logEvent(event: AnalyticsEvent) +} \ No newline at end of file diff --git a/app/src/main/java/com/kuit/findu/analytics/AnalyticsHelperImpl.kt b/app/src/main/java/com/kuit/findu/analytics/AnalyticsHelperImpl.kt new file mode 100644 index 00000000..f79af806 --- /dev/null +++ b/app/src/main/java/com/kuit/findu/analytics/AnalyticsHelperImpl.kt @@ -0,0 +1,21 @@ +package com.kuit.findu.analytics + +import com.google.firebase.analytics.FirebaseAnalytics +import com.google.firebase.analytics.logEvent +import javax.inject.Inject + +class AnalyticsHelperImpl @Inject constructor( + private val firebaseAnalytics: FirebaseAnalytics, +) : AnalyticsHelper { + override fun logEvent(event: AnalyticsEvent) { + firebaseAnalytics.logEvent(event.type) { + for (extra in event.extras) { + // Key, Value Max Length에 따른 slicing + param( + key = extra.key.take(40), + value = extra.value.take(100), + ) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/kuit/findu/analytics/di/FirebaseModule.kt b/app/src/main/java/com/kuit/findu/analytics/di/FirebaseModule.kt new file mode 100644 index 00000000..30fa006d --- /dev/null +++ b/app/src/main/java/com/kuit/findu/analytics/di/FirebaseModule.kt @@ -0,0 +1,37 @@ +package com.kuit.findu.analytics.di + +import com.google.firebase.Firebase +import com.google.firebase.analytics.FirebaseAnalytics +import com.google.firebase.analytics.analytics +import com.google.firebase.crashlytics.FirebaseCrashlytics +import com.google.firebase.crashlytics.crashlytics +import com.kuit.findu.analytics.AnalyticsHelper +import com.kuit.findu.analytics.AnalyticsHelperImpl +import dagger.Binds +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import javax.inject.Singleton + +@Module +@InstallIn(SingletonComponent::class) +abstract class FirebaseModule { + @Binds + @Singleton + abstract fun bindsAnalyticsHelper(analyticsHelperImpl: AnalyticsHelperImpl): AnalyticsHelper + + companion object { + @Provides + @Singleton + fun provideFirebaseAnalytics(): FirebaseAnalytics { + return Firebase.analytics + } + + @Provides + @Singleton + fun provideFirebaseCrashlytics(): FirebaseCrashlytics { + return Firebase.crashlytics + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/kuit/findu/data/dataremote/util/ErrorTrackingInterceptor.kt b/app/src/main/java/com/kuit/findu/data/dataremote/util/ErrorTrackingInterceptor.kt new file mode 100644 index 00000000..8550122f --- /dev/null +++ b/app/src/main/java/com/kuit/findu/data/dataremote/util/ErrorTrackingInterceptor.kt @@ -0,0 +1,45 @@ +package com.kuit.findu.data.dataremote.util + +import com.google.firebase.crashlytics.FirebaseCrashlytics +import com.google.firebase.crashlytics.recordException +import okhttp3.Interceptor +import okhttp3.Response +import javax.inject.Inject + +class ErrorTrackingInterceptor @Inject constructor( + private val firebaseCrashlytics: FirebaseCrashlytics, +) : Interceptor { + override fun intercept(chain: Interceptor.Chain): Response { + val request = chain.request() + val response: Response + + try { + response = chain.proceed(request) + } catch (e: Exception) { + // 1. 네트워크 자체가 끊긴 경우 등 (IOException) + firebaseCrashlytics.recordException(e) + throw e + } + + // 2. 서버에서 응답은 왔으나 4xx, 5xx 에러인 경우 + if (!response.isSuccessful) { + val code = response.code + + val url = request.url.toString() + + // Crashlytics에 상세 정보 기록 + val exceptionMessage = when (response.code) { + in (400..499) -> "Client $code Error" + in (500..599) -> "Server $code Error" + else -> "Unknown $code Error" + } + firebaseCrashlytics.recordException(Exception(exceptionMessage)) { + key("api_method", request.method) + key("api_url", url) + key("api_status", code) + } + } + + return response + } +} \ No newline at end of file diff --git a/app/src/main/java/com/kuit/findu/di/NetworkModule.kt b/app/src/main/java/com/kuit/findu/di/NetworkModule.kt index 76021961..034b54f6 100644 --- a/app/src/main/java/com/kuit/findu/di/NetworkModule.kt +++ b/app/src/main/java/com/kuit/findu/di/NetworkModule.kt @@ -1,11 +1,13 @@ package com.kuit.findu.di import android.content.Context +import com.google.firebase.crashlytics.FirebaseCrashlytics +import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory import com.kuit.findu.BuildConfig import com.kuit.findu.BuildConfig.DEBUG import com.kuit.findu.data.datalocal.datasource.TokenLocalDataSource import com.kuit.findu.data.dataremote.util.AuthInterceptor -import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory +import com.kuit.findu.data.dataremote.util.ErrorTrackingInterceptor import dagger.Module import dagger.Provides import dagger.hilt.InstallIn @@ -39,13 +41,15 @@ object NetworkModule { @Singleton fun providesOkHttpClient( loggingInterceptor: HttpLoggingInterceptor, - authInterceptor: AuthInterceptor + authInterceptor: AuthInterceptor, + errorTrackingInterceptor: ErrorTrackingInterceptor, ): OkHttpClient = OkHttpClient.Builder().apply { connectTimeout(10, TimeUnit.SECONDS) writeTimeout(10, TimeUnit.SECONDS) readTimeout(10, TimeUnit.SECONDS) if (DEBUG) addInterceptor(loggingInterceptor) + else addInterceptor(errorTrackingInterceptor) addInterceptor(authInterceptor) }.build() @@ -60,17 +64,25 @@ object NetworkModule { @Singleton fun provideAuthInterceptor( tokenLocalDataSource: TokenLocalDataSource, - @ApplicationContext context: Context + @ApplicationContext context: Context, ): AuthInterceptor { return AuthInterceptor(tokenLocalDataSource, context) } + @Provides + @Singleton + fun provideErrorTrackingInterceptor( + firebaseCrashlytics: FirebaseCrashlytics, + ): ErrorTrackingInterceptor { + return ErrorTrackingInterceptor(firebaseCrashlytics) + } + @ExperimentalSerializationApi @Provides @Singleton fun providesRetrofit( okHttpClient: OkHttpClient, - json: Json + json: Json, ): Retrofit = Retrofit.Builder() .baseUrl(BuildConfig.BASE_URL) diff --git a/app/src/main/java/com/kuit/findu/presentation/ui/home/HomeFragment.kt b/app/src/main/java/com/kuit/findu/presentation/ui/home/HomeFragment.kt index 93661b62..a5f2d68a 100644 --- a/app/src/main/java/com/kuit/findu/presentation/ui/home/HomeFragment.kt +++ b/app/src/main/java/com/kuit/findu/presentation/ui/home/HomeFragment.kt @@ -36,7 +36,7 @@ class HomeFragment : Fragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, - savedInstanceState: Bundle? + savedInstanceState: Bundle?, ): View { _binding = FragmentHomeBinding.inflate(inflater, container, false) return binding.root @@ -76,11 +76,22 @@ class HomeFragment : Fragment() { } is HomeUiEffect.ShowToast -> { - Toast.makeText(requireContext(), sideEffect.message, Toast.LENGTH_SHORT).show() + Toast.makeText( + requireContext(), + sideEffect.message, + Toast.LENGTH_SHORT + ).show() } - is HomeUiEffect.NavigateToProtectList -> TODO() - is HomeUiEffect.NavigateToReportList -> TODO() + is HomeUiEffect.NavigateToProtectList -> {} + is HomeUiEffect.NavigateToReportList -> {} + + is HomeUiEffect.NavigateToFindReport -> { + navigateToFindReport() + } + is HomeUiEffect.NavigateToLostReport -> { + navigateToLostReport() + } is HomeUiEffect.Dial -> call120() } @@ -110,7 +121,11 @@ class HomeFragment : Fragment() { homeViewModel.handleEvent(HomeUiEvent.OnAlarmButtonClick) }, onIndicatorSelected = { reportDurationType -> - homeViewModel.handleEvent(HomeUiEvent.OnHomeReportDurationClick(reportDurationType)) + homeViewModel.handleEvent( + HomeUiEvent.OnHomeReportDurationClick( + reportDurationType + ) + ) }, userNickname = uiState.nickname, navigateToProtectDetail = { protectAnimal -> @@ -128,13 +143,18 @@ class HomeFragment : Fragment() { onReportDialogDismiss = { homeViewModel.handleEvent(HomeUiEvent.OnReportDialogDismiss) }, - onLostReportClick = {}, - onFindReportClick = {}, + onLostReportClick = { + homeViewModel.navigateToLostReport() + }, + onFindReportClick = { + homeViewModel.navigateToFindReport() + }, onPhoneClicked = { homeViewModel.dial() }, - navigateToHomeExtra = { homeExtraButtonType-> - navigateToHomeExtra(homeExtraButtonType) }, + navigateToHomeExtra = { homeExtraButtonType -> + navigateToHomeExtra(homeExtraButtonType) + }, ) } @@ -192,6 +212,18 @@ class HomeFragment : Fragment() { } } + private fun navigateToLostReport() { + findNavController().navigate( + HomeFragmentDirections.actionFragmentHomeToFragmentMissingReport() + ) + } + + private fun navigateToFindReport() { + findNavController().navigate( + HomeFragmentDirections.actionFragmentHomeToFragmentWitnessReport() + ) + } + private fun openWebLink(url: String) { val intent = Intent(Intent.ACTION_VIEW, url.toUri()) requireActivity().startActivity(intent) diff --git a/app/src/main/java/com/kuit/findu/presentation/ui/home/viewmodel/HomeViewModel.kt b/app/src/main/java/com/kuit/findu/presentation/ui/home/viewmodel/HomeViewModel.kt index 2b74cffe..47c5f3c9 100644 --- a/app/src/main/java/com/kuit/findu/presentation/ui/home/viewmodel/HomeViewModel.kt +++ b/app/src/main/java/com/kuit/findu/presentation/ui/home/viewmodel/HomeViewModel.kt @@ -32,12 +32,16 @@ data class HomeUiState( val bannerCurrentPage: Int = 0, val isScrollToTopVisible: Boolean = false, val isReportDialogVisible: Boolean = false, - val locationPermission: Boolean = false + val locationPermission: Boolean = false, ) { val userHomeUserStatusType: HomeUserStatusType get() = when { !locationPermission -> HomeUserStatusType.LOCATION_DENIED - nickname.isEmpty() || nickname.equals(GUEST_NAME, ignoreCase = false) -> HomeUserStatusType.GUEST + nickname.isEmpty() || nickname.equals( + GUEST_NAME, + ignoreCase = false + ) -> HomeUserStatusType.GUEST + else -> HomeUserStatusType.MEMBER } } @@ -68,6 +72,8 @@ sealed class HomeUiEffect { data object NavigateToReportList : HomeUiEffect() data class NavigateToProtectDetail(val animal: ProtectAnimal) : HomeUiEffect() data class NavigateToReportDetail(val animal: ReportAnimal) : HomeUiEffect() + data object NavigateToLostReport : HomeUiEffect() + data object NavigateToFindReport : HomeUiEffect() data class OpenWebLink(val url: String) : HomeUiEffect() data class ShowToast(val message: String) : HomeUiEffect() @@ -77,7 +83,7 @@ sealed class HomeUiEffect { @HiltViewModel class HomeViewModel @Inject constructor( private val homeUseCase: GetHomeUseCase, - private val getNicknameUseCase: GetNicknameUseCase + private val getNicknameUseCase: GetNicknameUseCase, ) : ViewModel() { private val _uiState = MutableStateFlow(HomeUiState()) @@ -125,17 +131,21 @@ class HomeViewModel @Inject constructor( _uiState.update { it.copy(loadState = LoadState.Loading) } homeUseCase().fold( onSuccess = { data -> - _uiState.update { it.copy( - loadState = LoadState.Success, - homeData = data, - errorMessage = null - ) } + _uiState.update { + it.copy( + loadState = LoadState.Success, + homeData = data, + errorMessage = null + ) + } }, onFailure = { error -> - _uiState.update { it.copy( - loadState = LoadState.Error, - errorMessage = error.message ?: "데이터를 불러오는 중 오류가 발생했습니다." - ) } + _uiState.update { + it.copy( + loadState = LoadState.Error, + errorMessage = error.message ?: "데이터를 불러오는 중 오류가 발생했습니다." + ) + } } ) } @@ -154,29 +164,35 @@ class HomeViewModel @Inject constructor( homeUseCase().fold( onSuccess = { data -> - _uiState.update { it.copy( - loadState = LoadState.Success, - homeData = data, - errorMessage = null, - isRefreshing = false - ) } + _uiState.update { + it.copy( + loadState = LoadState.Success, + homeData = data, + errorMessage = null, + isRefreshing = false + ) + } }, onFailure = { error -> - _uiState.update { it.copy( - loadState = LoadState.Error, - errorMessage = error.message ?: "데이터를 새로고침하는 중 오류가 발생했습니다.", - isRefreshing = false - ) } + _uiState.update { + it.copy( + loadState = LoadState.Error, + errorMessage = error.message ?: "데이터를 새로고침하는 중 오류가 발생했습니다.", + isRefreshing = false + ) + } } ) } } private fun clearError() { - _uiState.update { it.copy( - errorMessage = null, - loadState = if (_uiState.value.homeData != null) LoadState.Success else LoadState.Idle - ) } + _uiState.update { + it.copy( + errorMessage = null, + loadState = if (_uiState.value.homeData != null) LoadState.Success else LoadState.Idle + ) + } } @@ -215,6 +231,17 @@ class HomeViewModel @Inject constructor( } } + fun navigateToLostReport() { + viewModelScope.launch { + _uiEffect.send(HomeUiEffect.NavigateToLostReport) + } + } + + fun navigateToFindReport() { + viewModelScope.launch { + _uiEffect.send(HomeUiEffect.NavigateToFindReport) + } + } fun dial() { viewModelScope.launch { diff --git a/app/src/main/java/com/kuit/findu/presentation/ui/login/viewmodel/LoginViewModel.kt b/app/src/main/java/com/kuit/findu/presentation/ui/login/viewmodel/LoginViewModel.kt index b7f70f43..8480dd4d 100644 --- a/app/src/main/java/com/kuit/findu/presentation/ui/login/viewmodel/LoginViewModel.kt +++ b/app/src/main/java/com/kuit/findu/presentation/ui/login/viewmodel/LoginViewModel.kt @@ -3,6 +3,8 @@ package com.kuit.findu.presentation.ui.login.viewmodel import android.util.Log import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.kuit.findu.analytics.AnalyticsHelper +import com.kuit.findu.analytics.logUserSignIn import com.kuit.findu.domain.usecase.SetNicknameUseCase import com.kuit.findu.domain.usecase.auth.PostGuestLoginUseCase import com.kuit.findu.domain.usecase.auth.PostLoginUseCase @@ -19,7 +21,8 @@ class LoginViewModel @Inject constructor( private val loginUseCase: PostLoginUseCase, private val guestLoginUseCase: PostGuestLoginUseCase, private val setAccessTokenUseCase: SetAccessTokenUseCase, - private val setNicknameUseCase: SetNicknameUseCase + private val setNicknameUseCase: SetNicknameUseCase, + private val analyticsHelper: AnalyticsHelper, ) : ViewModel() { private val _startMainActivity = MutableSharedFlow() val startMainActivity: SharedFlow = _startMainActivity @@ -34,6 +37,9 @@ class LoginViewModel @Inject constructor( if (loginData.isFirstLogin) { startOnboardingActivity(kakaoId = kakaoId) } else { + analyticsHelper.logUserSignIn( + userName = loginData.userInfo?.nickname ?: "Null Nickname", type = "kakao" + ) setAccessTokenUseCase(accessToken = loginData.userInfo!!.accessToken) setNicknameUseCase(nickname = loginData.userInfo.nickname) startMainActivity() @@ -44,11 +50,11 @@ class LoginViewModel @Inject constructor( } } - fun postGuestLogin(onSuccess: () -> Unit) { viewModelScope.launch { guestLoginUseCase.postGuestLogin() .onSuccess { loginData -> + analyticsHelper.logUserSignIn(userName = GUEST_NAME, type = "Guest") setAccessTokenUseCase(accessToken = loginData.accessToken) setNicknameUseCase(nickname = GUEST_NAME) onSuccess() @@ -61,7 +67,6 @@ class LoginViewModel @Inject constructor( } - private fun startMainActivity() { viewModelScope.launch { _startMainActivity.emit(Unit) diff --git a/app/src/main/java/com/kuit/findu/presentation/ui/main/MainActivity.kt b/app/src/main/java/com/kuit/findu/presentation/ui/main/MainActivity.kt index 4581d6f3..f1cc619f 100644 --- a/app/src/main/java/com/kuit/findu/presentation/ui/main/MainActivity.kt +++ b/app/src/main/java/com/kuit/findu/presentation/ui/main/MainActivity.kt @@ -7,22 +7,22 @@ import androidx.navigation.NavController import androidx.navigation.fragment.NavHostFragment import androidx.navigation.ui.setupWithNavController import com.kuit.findu.R +import com.kuit.findu.analytics.AnalyticsHelper +import com.kuit.findu.analytics.logScreenView import com.kuit.findu.databinding.ActivityMainBinding import dagger.hilt.android.AndroidEntryPoint +import javax.inject.Inject @AndroidEntryPoint class MainActivity : AppCompatActivity() { private lateinit var binding: ActivityMainBinding - + @Inject + lateinit var analyticsHelper: AnalyticsHelper override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - - - - binding = ActivityMainBinding.inflate(layoutInflater) setContentView(binding.root) @@ -39,6 +39,14 @@ class MainActivity : AppCompatActivity() { private fun setBottomNaviVisible(navController: NavController) { navController.addOnDestinationChangedListener { _, destination, _ -> + val screenName = try { + resources.getResourceEntryName(destination.id) + } catch (_: Exception) { + "unknown_screen" + } + + analyticsHelper.logScreenView(screenName) + binding.bnvMain.visibility = when (destination.id) { R.id.fragment_home, R.id.fragment_search, R.id.fragment_info, R.id.fragment_my -> View.VISIBLE R.id.fragment_search_detail_witness, R.id.fragment_search_detail_disappear, R.id.fragment_search_detail_protecting -> View.VISIBLE diff --git a/app/src/main/java/com/kuit/findu/presentation/ui/onboarding/viewmodel/OnboardingViewModel.kt b/app/src/main/java/com/kuit/findu/presentation/ui/onboarding/viewmodel/OnboardingViewModel.kt index b3a0e52a..779f3b49 100644 --- a/app/src/main/java/com/kuit/findu/presentation/ui/onboarding/viewmodel/OnboardingViewModel.kt +++ b/app/src/main/java/com/kuit/findu/presentation/ui/onboarding/viewmodel/OnboardingViewModel.kt @@ -5,6 +5,8 @@ import android.net.Uri import android.util.Log import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.kuit.findu.analytics.AnalyticsHelper +import com.kuit.findu.analytics.logUserSignUp import com.kuit.findu.domain.usecase.auth.PostCheckNicknameUseCase import com.kuit.findu.domain.usecase.auth.PostSignupUseCase import com.kuit.findu.presentation.type.DefaultProfileType @@ -35,6 +37,7 @@ class OnboardingViewModel @Inject constructor( @ApplicationContext private val context: Context, private val postCheckNicknameUseCase: PostCheckNicknameUseCase, private val postSignupUseCase: PostSignupUseCase, + private val analyticsHelper: AnalyticsHelper, ) : ViewModel() { private val _uiState = MutableStateFlow(OnboardingUiState()) val uiState: StateFlow = _uiState.asStateFlow() @@ -120,6 +123,7 @@ class OnboardingViewModel @Inject constructor( nickname = uiState.value.nickname, kakaoId = uiState.value.kakaoId ).onSuccess { + analyticsHelper.logUserSignUp(userName = uiState.value.nickname) startMainActivity() }.onFailure { e -> Log.d("http", "Error Message: : $e") diff --git a/app/src/main/java/com/kuit/findu/presentation/ui/report/WitnessReportFragment.kt b/app/src/main/java/com/kuit/findu/presentation/ui/report/WitnessReportFragment.kt index 629549e5..45a17d99 100644 --- a/app/src/main/java/com/kuit/findu/presentation/ui/report/WitnessReportFragment.kt +++ b/app/src/main/java/com/kuit/findu/presentation/ui/report/WitnessReportFragment.kt @@ -59,7 +59,7 @@ class WitnessReportFragment : Fragment() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - + resultLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> if (result.resultCode == AppCompatActivity.RESULT_OK) { val data = result.data?.getStringExtra(ReportLocationDialog.Companion.POST_TAG) diff --git a/build.gradle.kts b/build.gradle.kts index 309816ff..ebcb5dfd 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -4,5 +4,6 @@ plugins { alias(libs.plugins.kotlin.android) apply false alias(libs.plugins.dagger.hilt) apply false alias(libs.plugins.navigationSafeArgs) apply false - id("com.google.gms.google-services") version "4.4.2" apply false + alias(libs.plugins.googleServices) apply false + alias(libs.plugins.firebaseCrashlytics) apply false } \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index bd319424..0e29bbf2 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -3,11 +3,10 @@ accompanistPermissions = "0.37.3" agp = "8.7.3" coilCompose = "2.5.0" composeBom = "2024.04.01" -firebaseBom = "34.4.0" -firebaseBomVersion = "33.4.0" -firebaseConfig = "23.0.1" -googleFirebaseBom = "33.3.0" -kotlin = "1.9.24" +firebaseBom = "34.6.0" +firebaseCrashlytics = "3.0.6" +googleServices = "4.4.2" +kotlin = "2.0.21" coreKtx = "1.15.0" junit = "4.13.2" junitVersion = "1.2.1" @@ -37,8 +36,6 @@ playServicesLocation = "21.3.0" cameraCore = "1.4.1" kakao = "2.20.3" material3Android = "1.3.2" -firebaseCommonKtx = "22.0.1" - [libraries] accompanist-permissions = { module = "com.google.accompanist:accompanist-permissions", version.ref = "accompanistPermissions" } @@ -51,16 +48,13 @@ androidx-ui-tooling = { module = "androidx.compose.ui:ui-tooling" } androidx-ui-tooling-preview = { module = "androidx.compose.ui:ui-tooling-preview" } androidx-webkit = { module = "androidx.webkit:webkit", version.ref = "webkit" } coil-compose = { module = "io.coil-kt:coil-compose", version.ref = "coilCompose" } -firebase-analytics = { module = "com.google.firebase:firebase-analytics" } -firebase-analytics-ktx = { module = "com.google.firebase:firebase-analytics-ktx" } + +# Firebase firebase-bom = { module = "com.google.firebase:firebase-bom", version.ref = "firebaseBom" } -firebase-bom-v3330 = { module = "com.google.firebase:firebase-bom", version.ref = "googleFirebaseBom" } -firebase-bom-v3340 = { module = "com.google.firebase:firebase-bom", version.ref = "firebaseBomVersion" } -firebase-config = { module = "com.google.firebase:firebase-config" } -firebase-config-ktx = { module = "com.google.firebase:firebase-config-ktx" } -google-firebase-analytics = { module = "com.google.firebase:firebase-analytics" } -google-firebase-config = { module = "com.google.firebase:firebase-config", version.ref = "firebaseConfig" } -google-firebase-config-ktx = { module = "com.google.firebase:firebase-config-ktx" } +firebase-analytics-ktx = { module = "com.google.firebase:firebase-analytics" } +firebase-config-ktx = { module = "com.google.firebase:firebase-config" } +firebase-crashlytics = { module = "com.google.firebase:firebase-crashlytics"} + junit = { group = "junit", name = "junit", version.ref = "junit" } androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" } androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" } @@ -101,14 +95,16 @@ kakao-friend = { group = "com.kakao.sdk", name = "v2-friend", version.ref = "kak kakao-navi = { group = "com.kakao.sdk", name = "v2-navi", version.ref = "kakao" } kakao-cert = { group = "com.kakao.sdk", name = "v2-cert", version.ref = "kakao" } androidx-material3-android = { group = "androidx.compose.material3", name = "material3-android", version.ref = "material3Android" } -firebase-common-ktx = { group = "com.google.firebase", name = "firebase-common-ktx", version.ref = "firebaseCommonKtx" } [plugins] android-application = { id = "com.android.application", version.ref = "agp" } kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } +kotlin-compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } dagger-hilt = { id = "com.google.dagger.hilt.android", version.ref = "daggerHilt" } navigationSafeArgs = { id = "androidx.navigation.safeargs.kotlin", version.ref = "navigationFragmentKtx" } +googleServices = { id = "com.google.gms.google-services", version.ref = "googleServices" } +firebaseCrashlytics = { id = "com.google.firebase.crashlytics", version.ref = "firebaseCrashlytics" } [bundles] hilt = [