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

부산대 Android_이지은 6주차 2단계 #59

Open
wants to merge 15 commits into
base: jieunyume
Choose a base branch
from
Open
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
16 changes: 15 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,15 @@
# android-map-notification
# 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 창을 터치하면 초기 진입 화면이 호출된다.
15 changes: 15 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ plugins {
id("kotlin-kapt")
id("com.google.dagger.hilt.android")
id("kotlin-parcelize")
id("com.google.gms.google-services")
}

android {
Expand All @@ -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"
}
Expand Down Expand Up @@ -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")


}
22 changes: 16 additions & 6 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,28 @@
android:usesCleartextTraffic="true"
tools:targetApi="31">
<activity
android:name=".view.search.MainActivity"
android:windowSoftInputMode="adjustNothing"
android:exported="false" />
<activity
android:name=".view.map.MapActivity"
android:name=".view.map.SplashActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".view.search.MainActivity"
android:exported="false"
android:windowSoftInputMode="adjustNothing" />
<activity
android:name=".view.map.MapActivity"
android:exported="false">
</activity>
<service
android:name=".service.MyFirebaseMessagingService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
</application>

</manifest>
11 changes: 0 additions & 11 deletions app/src/main/java/campus/tech/kakao/map/MainActivity.kt

This file was deleted.

43 changes: 43 additions & 0 deletions app/src/main/java/campus/tech/kakao/map/NotificationUtil.kt
Original file line number Diff line number Diff line change
@@ -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())
}
Original file line number Diff line number Diff line change
@@ -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
Expand Down
52 changes: 52 additions & 0 deletions app/src/main/java/campus/tech/kakao/map/di/RemoteConfigModule.kt
Original file line number Diff line number Diff line change
@@ -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
}
Comment on lines +19 to +42
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

apply 나 also 를 적절하게 사용하면 좋습니다!

Suggested change
@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 provideFirebaseRemoteConfig(): FirebaseRemoteConfig {
return Firebase.remoteConfig.apply {
initRemoteConfig(this)
}
}
fun initRemoteConfig(remoteConfig: 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}")
}
}


@Singleton
@Provides
fun providesRemoteConfigDataSource(firebaseRemoteConfig: FirebaseRemoteConfig): RemoteConfigDataSource {
return RemoteConfigDataSource(firebaseRemoteConfig)
}



}
Original file line number Diff line number Diff line change
@@ -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

Expand All @@ -21,4 +22,8 @@ abstract class RepositoryModule {
@Binds
@Singleton
abstract fun bindDefaultSavedLocationRepository(impl: DefaultSavedLocationRepository) : SavedLocationRepository

@Binds
@Singleton
abstract fun bindDefaultRemoteConfigRepository(impl: DefaultRemoteConfigRepository) : RemoteConfigRepository
}
Original file line number Diff line number Diff line change
@@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package campus.tech.kakao.map
package campus.tech.kakao.map.di

import android.content.Context
import androidx.room.Room
Expand Down
6 changes: 6 additions & 0 deletions app/src/main/java/campus/tech/kakao/map/model/RemoteConfig.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package campus.tech.kakao.map.model

data class RemoteConfig(
val serviceState: String,
val serviceMessage: String
)
Original file line number Diff line number Diff line change
@@ -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)
)
}
Comment on lines +11 to +16
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

첫 실행시 firebase remote config 가 default 값으로 처리되거나 빈값으로 내려올 것 같아요. remote config fetch 를 해오는 메소드를 추가해보면 어떨까요?

}
Original file line number Diff line number Diff line change
@@ -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()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package campus.tech.kakao.map.model.repository

import campus.tech.kakao.map.model.RemoteConfig


interface RemoteConfigRepository {
fun getRemoteConfig(): RemoteConfig
}
Original file line number Diff line number Diff line change
@@ -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)
}
}
Loading