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 @@
+
+
+
diff --git a/build.gradle.kts b/build.gradle.kts
index d6b55841..49f2a696 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -4,6 +4,7 @@ plugins {
id("org.jetbrains.kotlin.android") version "1.9.0" apply false
id("org.jlleitschuh.gradle.ktlint") version "12.1.0" apply false
id("com.google.dagger.hilt.android") version "2.48.1" apply false
+ id("com.google.gms.google-services") version "4.4.2" apply false
}
allprojects {