diff --git a/README.md b/README.md index 00711097..2270fb20 100644 --- a/README.md +++ b/README.md @@ -1 +1,15 @@ -# android-map-notification \ No newline at end of file +# android-map-notification +## step1 기능목록 +- Firebase의 Remote Config 설정하기 + - 서비스 상태를 나타내는 매개변수를 각각 등록한다. + - 매개변수 이름:serviceState, serviceMessage +- 초기 진입 화면 추가하기 + - 서버 상태, UI 로딩 등에 대한 상태 관리를 한다. + - 매개변수 serviceState 값이 ON_SERVICE일 때만 초기 진입 화면이 지도 화면으로 넘어간다. + - 매개변수 serviceState 값이 ON_SERVICE이 아닌 경우에는 serviceMessage 값을 초기 진입 화면 하단에 표시하고 지도 화면으로 진입하지 않는다. +## step2 기능목록 +- Firebase Cloud Message(FCM) 설정하기 + - 테스트 메시지를 보낸다. + - 앱이 백그라운드 상태일 경우 FCM 기본 값을 사용하여 Notification을 발생한다. + - 앱이 포그라운드 상태일 경우 커스텀 Notification을 발생한다. + - Notification 창을 터치하면 초기 진입 화면이 호출된다. \ No newline at end of file diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 6caa059d..af89b737 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -6,6 +6,7 @@ plugins { id("kotlin-kapt") id("com.google.dagger.hilt.android") id("kotlin-parcelize") + id("com.google.gms.google-services") } android { @@ -26,6 +27,10 @@ android { buildConfigField("String", "KAKAO_API_KEY", getApiKey("KAKAO_API_KEY")) buildConfigField("String", "KAKAO_REST_API_KEY", getApiKey("KAKAO_REST_API_KEY")) buildConfigField("String", "BASE_URL", getApiKey("BASE_URL")) + buildConfigField("String", "SERVICE_STATE", getApiKey("SERVICE_STATE")) + buildConfigField("String", "SERVICE_MESSAGE", getApiKey("SERVICE_MESSAGE")) + buildConfigField("String", "CHANNEL_ID", getApiKey("CHANNEL_ID")) + buildConfigField("String", "CHANNEL_NAME", getApiKey("CHANNEL_NAME")) testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } @@ -91,4 +96,14 @@ dependencies { // hilt implementation("com.google.dagger:hilt-android:2.48.1") kapt("com.google.dagger:hilt-compiler:2.48.1") + //firebase sdk + implementation(platform("com.google.firebase:firebase-bom:33.1.2")) + implementation("com.google.firebase:firebase-analytics-ktx") + + implementation("com.google.firebase:firebase-config-ktx:22.0.0") + implementation("com.google.firebase:firebase-messaging-ktx:24.0.0") + // splash + implementation("androidx.core:core-splashscreen:1.0.0-rc01") + + } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 278d536b..f14046c7 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -17,18 +17,28 @@ android:usesCleartextTraffic="true" tools:targetApi="31"> - - + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/MainActivity.kt b/app/src/main/java/campus/tech/kakao/map/MainActivity.kt deleted file mode 100644 index 95b43803..00000000 --- a/app/src/main/java/campus/tech/kakao/map/MainActivity.kt +++ /dev/null @@ -1,11 +0,0 @@ -package campus.tech.kakao.map - -import android.os.Bundle -import androidx.appcompat.app.AppCompatActivity - -class MainActivity : AppCompatActivity() { - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContentView(R.layout.activity_main) - } -} diff --git a/app/src/main/java/campus/tech/kakao/map/NotificationUtil.kt b/app/src/main/java/campus/tech/kakao/map/NotificationUtil.kt new file mode 100644 index 00000000..012732e2 --- /dev/null +++ b/app/src/main/java/campus/tech/kakao/map/NotificationUtil.kt @@ -0,0 +1,43 @@ +package campus.tech.kakao.map + +import android.app.NotificationManager +import android.app.PendingIntent +import android.content.Context +import android.content.Intent +import androidx.core.app.NotificationCompat +import android.graphics.BitmapFactory +import campus.tech.kakao.map.view.map.SplashActivity +import campus.tech.kakao.map.view.search.MainActivity + +private val NOTIFICATION_ID = 0 +private val REQUEST_CODE = 0 +private val FLAGS = 0 + +fun NotificationManager.sendNotification(messageTitle: String, messageBody: String, applicationContext: Context) { + val contentIntent = Intent(applicationContext, SplashActivity::class.java) + + val contentPendingIntent = PendingIntent.getActivity( + applicationContext, + NOTIFICATION_ID, + contentIntent, + PendingIntent.FLAG_IMMUTABLE + ) + + val mapImage = BitmapFactory.decodeResource( + applicationContext.resources, + R.drawable.map_icon2 + ) + + val builder = NotificationCompat.Builder( + applicationContext, + BuildConfig.CHANNEL_ID + ).setSmallIcon(R.drawable.map_icon2) + .setContentTitle(messageTitle) + .setContentText(messageBody) + .setContentIntent(contentPendingIntent) + .setLargeIcon(mapImage) + .setPriority(NotificationCompat.PRIORITY_DEFAULT) + .setAutoCancel(true) + + notify(NOTIFICATION_ID, builder.build()) +} \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/LocationModule.kt b/app/src/main/java/campus/tech/kakao/map/di/LocationModule.kt similarity index 97% rename from app/src/main/java/campus/tech/kakao/map/LocationModule.kt rename to app/src/main/java/campus/tech/kakao/map/di/LocationModule.kt index aa61a8e5..32986d20 100644 --- a/app/src/main/java/campus/tech/kakao/map/LocationModule.kt +++ b/app/src/main/java/campus/tech/kakao/map/di/LocationModule.kt @@ -1,4 +1,4 @@ -package campus.tech.kakao.map +package campus.tech.kakao.map.di import android.content.Context import campus.tech.kakao.map.model.datasource.KakaoAPI diff --git a/app/src/main/java/campus/tech/kakao/map/di/RemoteConfigModule.kt b/app/src/main/java/campus/tech/kakao/map/di/RemoteConfigModule.kt new file mode 100644 index 00000000..6b944844 --- /dev/null +++ b/app/src/main/java/campus/tech/kakao/map/di/RemoteConfigModule.kt @@ -0,0 +1,52 @@ +package campus.tech.kakao.map.di + +import android.util.Log +import campus.tech.kakao.map.model.datasource.RemoteConfigDataSource +import campus.tech.kakao.map.model.repository.RemoteConfigRepository +import com.google.firebase.Firebase +import com.google.firebase.remoteconfig.FirebaseRemoteConfig +import com.google.firebase.remoteconfig.remoteConfig +import com.google.firebase.remoteconfig.remoteConfigSettings +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import javax.inject.Singleton + +@Module +@InstallIn(SingletonComponent::class) +object RemoteConfigModule { + @Singleton + @Provides + fun provideFirebaseRemoteConfig(): FirebaseRemoteConfig { + val remoteConfig = Firebase.remoteConfig + return initRemoteConfig(remoteConfig) + } + + fun initRemoteConfig(remoteConfig: FirebaseRemoteConfig): FirebaseRemoteConfig { + val configSettings = remoteConfigSettings { + minimumFetchIntervalInSeconds = 0 // 바로바로 가져옴 + } + remoteConfig.setConfigSettingsAsync(configSettings) + remoteConfig.fetchAndActivate() + .addOnCompleteListener { + if (it.isSuccessful) { + Log.d("jieun", "Successful ${it.result}") + } else { + Log.d("jieun", "Failed ${it.result}") + } + }.addOnFailureListener { + Log.d("jieun", "Exception ${it.message}") + } + return remoteConfig + } + + @Singleton + @Provides + fun providesRemoteConfigDataSource(firebaseRemoteConfig: FirebaseRemoteConfig): RemoteConfigDataSource { + return RemoteConfigDataSource(firebaseRemoteConfig) + } + + + +} \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/RepositoryModule.kt b/app/src/main/java/campus/tech/kakao/map/di/RepositoryModule.kt similarity index 71% rename from app/src/main/java/campus/tech/kakao/map/RepositoryModule.kt rename to app/src/main/java/campus/tech/kakao/map/di/RepositoryModule.kt index bdbc3e66..501baa5b 100644 --- a/app/src/main/java/campus/tech/kakao/map/RepositoryModule.kt +++ b/app/src/main/java/campus/tech/kakao/map/di/RepositoryModule.kt @@ -1,13 +1,14 @@ -package campus.tech.kakao.map +package campus.tech.kakao.map.di import campus.tech.kakao.map.model.repository.DefaultLocationRepository +import campus.tech.kakao.map.model.repository.DefaultRemoteConfigRepository import campus.tech.kakao.map.model.repository.DefaultSavedLocationRepository import campus.tech.kakao.map.model.repository.LocationRepository +import campus.tech.kakao.map.model.repository.RemoteConfigRepository import campus.tech.kakao.map.model.repository.SavedLocationRepository import dagger.Binds import dagger.Module import dagger.hilt.InstallIn -import dagger.hilt.android.components.ViewModelComponent import dagger.hilt.components.SingletonComponent import javax.inject.Singleton @@ -21,4 +22,8 @@ abstract class RepositoryModule { @Binds @Singleton abstract fun bindDefaultSavedLocationRepository(impl: DefaultSavedLocationRepository) : SavedLocationRepository + + @Binds + @Singleton + abstract fun bindDefaultRemoteConfigRepository(impl: DefaultRemoteConfigRepository) : RemoteConfigRepository } \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/RetrofitInstanceModule.kt b/app/src/main/java/campus/tech/kakao/map/di/RetrofitInstanceModule.kt similarity index 94% rename from app/src/main/java/campus/tech/kakao/map/RetrofitInstanceModule.kt rename to app/src/main/java/campus/tech/kakao/map/di/RetrofitInstanceModule.kt index 43ce45ce..b5ea0890 100644 --- a/app/src/main/java/campus/tech/kakao/map/RetrofitInstanceModule.kt +++ b/app/src/main/java/campus/tech/kakao/map/di/RetrofitInstanceModule.kt @@ -1,7 +1,9 @@ -package campus.tech.kakao.map +package campus.tech.kakao.map.di import android.os.Looper import android.widget.Toast +import campus.tech.kakao.map.App +import campus.tech.kakao.map.BuildConfig import campus.tech.kakao.map.model.datasource.KakaoAPI import dagger.Module import dagger.Provides diff --git a/app/src/main/java/campus/tech/kakao/map/SavedLocationModule.kt b/app/src/main/java/campus/tech/kakao/map/di/SavedLocationModule.kt similarity index 96% rename from app/src/main/java/campus/tech/kakao/map/SavedLocationModule.kt rename to app/src/main/java/campus/tech/kakao/map/di/SavedLocationModule.kt index 97891b6f..33620a7a 100644 --- a/app/src/main/java/campus/tech/kakao/map/SavedLocationModule.kt +++ b/app/src/main/java/campus/tech/kakao/map/di/SavedLocationModule.kt @@ -1,4 +1,4 @@ -package campus.tech.kakao.map +package campus.tech.kakao.map.di import android.content.Context import androidx.room.Room diff --git a/app/src/main/java/campus/tech/kakao/map/model/RemoteConfig.kt b/app/src/main/java/campus/tech/kakao/map/model/RemoteConfig.kt new file mode 100644 index 00000000..b9010ce4 --- /dev/null +++ b/app/src/main/java/campus/tech/kakao/map/model/RemoteConfig.kt @@ -0,0 +1,6 @@ +package campus.tech.kakao.map.model + +data class RemoteConfig( + val serviceState: String, + val serviceMessage: String +) \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/model/datasource/RemoteConfigDataSource.kt b/app/src/main/java/campus/tech/kakao/map/model/datasource/RemoteConfigDataSource.kt new file mode 100644 index 00000000..0ec31f7a --- /dev/null +++ b/app/src/main/java/campus/tech/kakao/map/model/datasource/RemoteConfigDataSource.kt @@ -0,0 +1,17 @@ +package campus.tech.kakao.map.model.datasource + +import campus.tech.kakao.map.BuildConfig +import campus.tech.kakao.map.model.RemoteConfig +import com.google.firebase.remoteconfig.FirebaseRemoteConfig +import javax.inject.Inject + +class RemoteConfigDataSource @Inject constructor( + private val firebaseRemoteConfig: FirebaseRemoteConfig +){ + fun getRemoteConfig(): RemoteConfig { + return RemoteConfig( + serviceState = firebaseRemoteConfig.getString(BuildConfig.SERVICE_STATE), + serviceMessage = firebaseRemoteConfig.getString(BuildConfig.SERVICE_MESSAGE) + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/model/repository/DefaultRemoteConfigRepository.kt b/app/src/main/java/campus/tech/kakao/map/model/repository/DefaultRemoteConfigRepository.kt new file mode 100644 index 00000000..5a1cbaa8 --- /dev/null +++ b/app/src/main/java/campus/tech/kakao/map/model/repository/DefaultRemoteConfigRepository.kt @@ -0,0 +1,13 @@ +package campus.tech.kakao.map.model.repository + +import campus.tech.kakao.map.model.RemoteConfig +import campus.tech.kakao.map.model.datasource.RemoteConfigDataSource +import javax.inject.Inject + +class DefaultRemoteConfigRepository @Inject constructor( + private val remoteConfigDataSource: RemoteConfigDataSource +): RemoteConfigRepository { + override fun getRemoteConfig(): RemoteConfig { + return remoteConfigDataSource.getRemoteConfig() + } +} \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/model/repository/RemoteConfigRepository.kt b/app/src/main/java/campus/tech/kakao/map/model/repository/RemoteConfigRepository.kt new file mode 100644 index 00000000..1f6537c8 --- /dev/null +++ b/app/src/main/java/campus/tech/kakao/map/model/repository/RemoteConfigRepository.kt @@ -0,0 +1,8 @@ +package campus.tech.kakao.map.model.repository + +import campus.tech.kakao.map.model.RemoteConfig + + +interface RemoteConfigRepository { + fun getRemoteConfig(): RemoteConfig +} \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/service/MyFirebaseMessagingService.kt b/app/src/main/java/campus/tech/kakao/map/service/MyFirebaseMessagingService.kt new file mode 100644 index 00000000..c1077e7e --- /dev/null +++ b/app/src/main/java/campus/tech/kakao/map/service/MyFirebaseMessagingService.kt @@ -0,0 +1,24 @@ +package campus.tech.kakao.map.service + +import android.app.NotificationManager +import android.util.Log +import androidx.core.content.ContextCompat +import campus.tech.kakao.map.sendNotification +import com.google.firebase.messaging.FirebaseMessagingService +import com.google.firebase.messaging.RemoteMessage + +class MyFirebaseMessagingService : FirebaseMessagingService() { + override fun onMessageReceived(remoteMessage: RemoteMessage) { + Log.d("jieun", "From: ${remoteMessage.from}") + + remoteMessage.notification?.let { + Log.d("jieun", "Message Notification: ${it.title} ${it.body}") + sendNotification(it.title!!, it.body!!) + } + } + + private fun sendNotification(messageTitle: String, messageBody: String) { + val notificationManager = ContextCompat.getSystemService(applicationContext, NotificationManager::class.java) as NotificationManager + notificationManager.sendNotification(messageTitle, messageBody, applicationContext) + } +} \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/view/map/MapActivity.kt b/app/src/main/java/campus/tech/kakao/map/view/map/MapActivity.kt index 011ec8e2..6dcc7216 100644 --- a/app/src/main/java/campus/tech/kakao/map/view/map/MapActivity.kt +++ b/app/src/main/java/campus/tech/kakao/map/view/map/MapActivity.kt @@ -1,15 +1,31 @@ package campus.tech.kakao.map.view.map +import android.animation.ObjectAnimator +import android.animation.PropertyValuesHolder +import android.app.AlertDialog +import android.app.NotificationChannel +import android.app.NotificationManager import android.content.Intent +import android.content.pm.PackageManager import android.graphics.Color +import android.net.Uri +import android.os.Build import android.os.Bundle +import android.provider.Settings import android.util.Log import android.view.View -import android.widget.EditText -import android.widget.TextView +import android.view.animation.AnticipateInterpolator +import android.widget.Toast +import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.viewModels import androidx.appcompat.app.AppCompatActivity import androidx.constraintlayout.widget.ConstraintLayout +import androidx.core.animation.doOnEnd +import androidx.core.content.ContextCompat +import androidx.core.splashscreen.SplashScreen +import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen +import androidx.lifecycle.Observer +import campus.tech.kakao.map.BuildConfig import campus.tech.kakao.map.R import campus.tech.kakao.map.databinding.ActivityMapBinding import campus.tech.kakao.map.databinding.ErrorMapBinding @@ -17,16 +33,17 @@ import campus.tech.kakao.map.databinding.MapBottomSheetBinding import campus.tech.kakao.map.model.Location import campus.tech.kakao.map.view.search.MainActivity import campus.tech.kakao.map.viewmodel.LocationViewModel +import campus.tech.kakao.map.viewmodel.RemoteConfigViewModel import com.google.android.material.bottomsheet.BottomSheetBehavior import com.kakao.vectormap.KakaoMap import com.kakao.vectormap.KakaoMapReadyCallback import com.kakao.vectormap.LatLng import com.kakao.vectormap.MapLifeCycleCallback -import com.kakao.vectormap.MapView import com.kakao.vectormap.label.LabelOptions import com.kakao.vectormap.label.LabelStyle import com.kakao.vectormap.label.LabelStyles import dagger.hilt.android.AndroidEntryPoint +import campus.tech.kakao.map.model.RemoteConfig @AndroidEntryPoint class MapActivity : AppCompatActivity() { @@ -36,8 +53,9 @@ class MapActivity : AppCompatActivity() { private lateinit var activityMapBinding: ActivityMapBinding private lateinit var errorMapBinding: ErrorMapBinding private lateinit var mapBottomSheetBinding: MapBottomSheetBinding + private lateinit var splashScreen: SplashScreen - companion object{ + companion object { private const val DEFAULT_LONGITUDE = 127.115587 private const val DEFAULT_LATITUDE = 37.406960 } @@ -50,9 +68,17 @@ class MapActivity : AppCompatActivity() { errorMapBinding = ErrorMapBinding.inflate(layoutInflater) mapBottomSheetBinding = activityMapBinding.mapBottomSheet bottomSheetBehavior = BottomSheetBehavior.from(mapBottomSheetBinding.bottomSheetLayout) - - setupEditText() setupMapView() + setupEditText() + + createChannel( + BuildConfig.CHANNEL_ID, + BuildConfig.CHANNEL_NAME + ) + askNotificationPermission() + } + + private fun updateConfigs(remoteConfig: RemoteConfig) { } override fun onResume() { @@ -90,7 +116,7 @@ class MapActivity : AppCompatActivity() { showLabel(location, kakaoMap) showBottomSheet(location) locationViewModel.addLastLocation(location) - } else{ + } else { hideBottomSheet() } } @@ -98,7 +124,7 @@ class MapActivity : AppCompatActivity() { override fun getPosition(): LatLng { if (location != null) { return LatLng.from(location.latitude, location.longitude) - } else{ + } else { return LatLng.from(DEFAULT_LATITUDE, DEFAULT_LONGITUDE) } @@ -110,7 +136,8 @@ class MapActivity : AppCompatActivity() { private fun showErrorMessage(error: Exception) { runOnUiThread { setContentView(errorMapBinding.root) - errorMapBinding.errorMessageTextView.text = "지도 인증을 실패했습니다.\n다시 시도해주세요.\n\n" + error.message + errorMapBinding.errorMessageTextView.text = + "지도 인증을 실패했습니다.\n다시 시도해주세요.\n\n" + error.message } } @@ -138,14 +165,17 @@ class MapActivity : AppCompatActivity() { private fun showBottomSheet(location: Location) { mapBottomSheetBinding.bottomSheetLayout.visibility = View.VISIBLE mapBottomSheetBinding.bottomSheetTitle.text = location.title - Log.d("jieun", "mapBottomSheetBinding.bottomSheetTitle.text:"+mapBottomSheetBinding.bottomSheetTitle.text) + Log.d( + "jieun", + "mapBottomSheetBinding.bottomSheetTitle.text:" + mapBottomSheetBinding.bottomSheetTitle.text + ) mapBottomSheetBinding.bottomSheetAddress.text = location.address bottomSheetBehavior.state = BottomSheetBehavior.STATE_COLLAPSED } private fun getLocation(): Location? { var location = getLocationByIntent() - if(location == null) { + if (location == null) { location = locationViewModel.getLastLocation() } return location @@ -154,10 +184,82 @@ class MapActivity : AppCompatActivity() { private fun getLocationByIntent(): Location? { if (intent.hasExtra("location")) { - val location = intent.getParcelableExtra("location", Location::class.java) // API 레벨 오류, 실행에는 문제없다. - Log.d("jieun","getLocationByIntent location "+location.toString()) + val location = + intent.getParcelableExtra("location", Location::class.java) // API 레벨 오류, 실행에는 문제없다. + Log.d("jieun", "getLocationByIntent location " + location.toString()) return location } return null } + + // 6주차 + 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, + android.Manifest.permission.POST_NOTIFICATIONS + ) == PackageManager.PERMISSION_GRANTED + ) { + // FCM SDK (and your app) can post notifications. + } else if (shouldShowRequestPermissionRationale(android.Manifest.permission.POST_NOTIFICATIONS)) { + // 권한 요청 이유를 설명하는 UI를 표시 + showNotificationPermissionDialog() + } else { + // Directly ask for the permission + requestPermissionLauncher.launch(android.Manifest.permission.POST_NOTIFICATIONS) + } + } + } + + private fun showNotificationPermissionDialog() { + AlertDialog.Builder(this@MapActivity).apply { + setTitle("알림 권한 요청") + setMessage( + String.format( + "다양한 알림 소식을 받기 위해 권한을 허용하시겠어요?\n(알림 에서 %s의 알림 권한을 허용해주세요.)", + getString(R.string.app_name) + ) + ) + setPositiveButton("네") { _, _ -> + val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS) + val uri = Uri.fromParts("package", packageName, null) + intent.data = uri + startActivity(intent) + } + setNegativeButton("아니요") { _, _ -> } + show() + } + } + + private val requestPermissionLauncher = registerForActivityResult( + ActivityResultContracts.RequestPermission(), + ) { isGranted: Boolean -> + if (isGranted) { + Toast.makeText(this, "알림이 허용되었습니다.", Toast.LENGTH_SHORT) + } else { + Toast.makeText(this, "알림이 거부되었습니다.", Toast.LENGTH_SHORT) + } + } + + private fun createChannel(channelId: String, channelName: String) { + // TODO: Step 1.6 START create a channel + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + val notificationChannel = NotificationChannel( + channelId, + channelName, + NotificationManager.IMPORTANCE_DEFAULT + ).apply { + setShowBadge(false) + } + + notificationChannel.enableLights(true) + notificationChannel.lightColor = Color.RED + notificationChannel.enableVibration(true) + notificationChannel.description = "커피 이벤트 홍보" + + val notificationManager = getSystemService(NotificationManager::class.java) + notificationManager.createNotificationChannel(notificationChannel) + } + } } \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/view/map/SplashActivity.kt b/app/src/main/java/campus/tech/kakao/map/view/map/SplashActivity.kt new file mode 100644 index 00000000..b32d3c55 --- /dev/null +++ b/app/src/main/java/campus/tech/kakao/map/view/map/SplashActivity.kt @@ -0,0 +1,56 @@ +package campus.tech.kakao.map.view.map + +import android.content.Intent +import android.os.Bundle +import android.os.Handler +import android.os.Looper +import android.util.Log +import android.view.View +import androidx.activity.enableEdgeToEdge +import androidx.activity.viewModels +import androidx.appcompat.app.AppCompatActivity +import androidx.core.view.ViewCompat +import androidx.core.view.WindowInsetsCompat +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.Observer +import androidx.lifecycle.lifecycleScope +import androidx.lifecycle.repeatOnLifecycle +import campus.tech.kakao.map.R +import campus.tech.kakao.map.databinding.ActivitySplashBinding +import campus.tech.kakao.map.view.search.MainActivity +import campus.tech.kakao.map.viewmodel.RemoteConfigViewModel +import dagger.hilt.android.AndroidEntryPoint +import kotlinx.coroutines.launch + +@AndroidEntryPoint +class SplashActivity : AppCompatActivity() { + private lateinit var activitySplashBinding: ActivitySplashBinding + private val remoteConfigViewModel: RemoteConfigViewModel by viewModels() + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + activitySplashBinding = ActivitySplashBinding.inflate(layoutInflater) + setContentView(activitySplashBinding.root) + + setupSplashScreen() + } + + private fun setupSplashScreen() { + val isOnService = remoteConfigViewModel.isOnService() + Log.d("jieun", "isOnService: " + isOnService) + if (isOnService) { + Handler(Looper.getMainLooper()).postDelayed({ + // 일정 시간이 지나면 MapActivity로 이동 + val intent = Intent(this, MapActivity::class.java) + startActivity(intent) + finish() + + }, 1000) + } else { + activitySplashBinding.serverErrorMessage.visibility = View.VISIBLE + activitySplashBinding.serverErrorMessage.text = + remoteConfigViewModel.getServiceMessage() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/viewmodel/RemoteConfigViewModel.kt b/app/src/main/java/campus/tech/kakao/map/viewmodel/RemoteConfigViewModel.kt new file mode 100644 index 00000000..9cd2783b --- /dev/null +++ b/app/src/main/java/campus/tech/kakao/map/viewmodel/RemoteConfigViewModel.kt @@ -0,0 +1,32 @@ +package campus.tech.kakao.map.viewmodel + +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import campus.tech.kakao.map.model.RemoteConfig +import campus.tech.kakao.map.model.SavedLocation +import campus.tech.kakao.map.model.repository.RemoteConfigRepository +import dagger.hilt.android.lifecycle.HiltViewModel +import javax.inject.Inject + +@HiltViewModel +class RemoteConfigViewModel @Inject constructor( + remoteConfigRepository: RemoteConfigRepository +) : ViewModel() { + + private val _remoteConfigLiveData = MutableLiveData() + val remoteConfigLiveData: LiveData get() = _remoteConfigLiveData + + init { + _remoteConfigLiveData.value = remoteConfigRepository.getRemoteConfig() + } + fun isOnService(): Boolean { + return _remoteConfigLiveData.value?.serviceState.equals("ON_SERVICE") + } + + fun getServiceMessage(): String{ + return _remoteConfigLiveData.value?.serviceMessage.toString() + } + + +} \ No newline at end of file diff --git a/app/src/main/res/drawable/map_icon.png b/app/src/main/res/drawable/map_icon.png new file mode 100644 index 00000000..644d3ea1 Binary files /dev/null and b/app/src/main/res/drawable/map_icon.png differ diff --git a/app/src/main/res/drawable/map_icon2.png b/app/src/main/res/drawable/map_icon2.png new file mode 100644 index 00000000..f9e6f427 Binary files /dev/null and b/app/src/main/res/drawable/map_icon2.png differ diff --git a/app/src/main/res/layout/activity_splash.xml b/app/src/main/res/layout/activity_splash.xml new file mode 100644 index 00000000..5bc97b89 --- /dev/null +++ b/app/src/main/res/layout/activity_splash.xml @@ -0,0 +1,32 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml index 05ed4b9e..01b4b936 100644 --- a/app/src/main/res/values/themes.xml +++ b/app/src/main/res/values/themes.xml @@ -5,5 +5,13 @@ + + +