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주차 Step2 #54

Open
wants to merge 17 commits into
base: kimseongyu
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 15 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
62 changes: 48 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,27 @@

## Layout requirements

**Splash Screen**

Splash Screen

- Logo is Center of screen
- serviceMessage display on the bottom

**Kakao map**

Display kakao Map
Kakao Map

- Display selected search result using `bottom sheet`
- When onMapError() is called, print error message
- Save last location before app closed, and when app is started, focusing that location
- Using `kakaomap.Mapview` for display map
- Display selected search result using `bottom sheet`

Search window button

- If Search window button is clicked, go to _Save search keyword_
- _Stack Save search keyword_ on top of the this window
- Looks like search bar

Error Screen

- Print error message

**Save search keyword**

Expand All @@ -29,31 +38,50 @@ Saved search keyword list

Search result list

- Using `RecyclerView` to implement about search result list
- Using `RecyclerView` to implement about search result list
- It scrolls vertically

**Service**

When Firebase server send message
- If App is in the background, notification is generated using FCM defaults
- If App is in the foreground, custom notification is generated

## Function List

**Kakao map**
**Splash Screen**

Display Splash Screen

- Using `Firebase’s RemoteConfig` to set parameter
- When serviceState is ON_SERVICE, Switching screen to **Kakao map**
- When serviceState is not ON_SERVICE, display serviceMessage on the bottom and not switching screen

Ask Permission

- Request POST_NOTIFICATIONS permission

**Kakao map**

Display kakao Map

- Display selected search result using `bottom sheet`
- When onMapError() is called, print error message
- Display selected search result using `bottom sheet`
- Save last location before app closed, and when app is started, focusing that location

Go to _Save serach keyword_
Go to *Save serach keyword*

- If Search window button is clicked, go to *Save search keyword*
- *Stack Save search keyword* on top of the this window

- If Search window button is clicked, go to _Save search keyword_
- _Stack Save search keyword_ on top of the this window
Display Error Screen

- When onMapError() is called, print error message

**Save search keyword**

Requirements Rule

- Using `SQLite` to save search data
- Using `SQLite` to save search data
- When application is restart, data is maintained
- Apply the MVVM architectural pattern

Expand All @@ -74,3 +102,9 @@ Search result list
- There are at least 15 search results
- Search results have search word as categories
- Selected item is added to the saved search word list, and display location on the kakao map

**Service**

Call initial screen

- When touching notification window
3 changes: 2 additions & 1 deletion app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ plugins {
id("kotlin-parcelize")
id("kotlin-kapt")
id("com.google.dagger.hilt.android")
// id("com.google.gms.google-services")
id("com.google.gms.google-services")
}

android {
Expand Down Expand Up @@ -78,6 +78,7 @@ dependencies {
implementation("androidx.test:core-ktx:1.6.1")
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.3")
implementation("androidx.room:room-runtime:2.6.1")
implementation("androidx.activity:activity:1.8.0")
kapt("androidx.room:room-compiler:2.6.1")
implementation("com.google.dagger:hilt-android:2.48.1")
kapt("com.google.dagger:hilt-compiler:2.48.1")
Expand Down
13 changes: 13 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>

<application
android:name=".MyApplication"
Expand All @@ -17,6 +18,9 @@
android:supportsRtl="true"
android:theme="@style/Theme.Map"
tools:targetApi="31">
<activity
android:name=".view.splashscreen.SplashScreenActivity"
android:exported="false" />
<activity
android:name=".view.kakaomap.KakaoMapActivity"
android:exported="false" />
Expand All @@ -32,6 +36,15 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

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

</manifest>
9 changes: 7 additions & 2 deletions app/src/main/java/campus/tech/kakao/map/AppModule.kt
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
package campus.tech.kakao.map

import android.content.Context
import android.content.SharedPreferences
import campus.tech.kakao.map.model.search.SearchKeywordDao
import campus.tech.kakao.map.repository.kakaomap.LastPositionRepository
import campus.tech.kakao.map.repository.search.KakaoSearchKeywordAPI
import campus.tech.kakao.map.repository.search.SavedSearchKeywordRepository
import campus.tech.kakao.map.repository.search.SearchRepository
import campus.tech.kakao.map.repository.splashscreen.FirebaseRepository
import com.google.firebase.remoteconfig.FirebaseRemoteConfig
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton

Expand All @@ -32,4 +32,9 @@ object AppModule {
@Singleton
fun provideLastPositionRepository(sharedPreferences: SharedPreferences) =
LastPositionRepository(sharedPreferences)

@Provides
@Singleton
fun provideFirebaseRepository(remoteConfig: FirebaseRemoteConfig) =
FirebaseRepository(remoteConfig)
}
13 changes: 0 additions & 13 deletions app/src/main/java/campus/tech/kakao/map/MainActivity.kt

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package campus.tech.kakao.map.model.splashscreen

data class ServiceState(
var state: String,
var msg: String
)

object ServiceRemoteConfig {
const val SERVICE_STATE = "serviceState"
const val SERVICE_MESSAGE = "serviceMessage"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package campus.tech.kakao.map.repository.splashscreen

import android.content.Context
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.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton

@Module
@InstallIn(SingletonComponent::class)
object FirebaseModule {

@Provides
@Singleton
fun provideRemoteConfig(@ApplicationContext context: Context): FirebaseRemoteConfig {
val remoteConfig: FirebaseRemoteConfig = Firebase.remoteConfig
val configSettings = remoteConfigSettings {
minimumFetchIntervalInSeconds = 0
}
remoteConfig.setConfigSettingsAsync(configSettings)
return remoteConfig
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package campus.tech.kakao.map.repository.splashscreen

import campus.tech.kakao.map.model.splashscreen.ServiceState
import campus.tech.kakao.map.model.splashscreen.ServiceRemoteConfig.SERVICE_MESSAGE
import campus.tech.kakao.map.model.splashscreen.ServiceRemoteConfig.SERVICE_STATE
import com.google.firebase.remoteconfig.FirebaseRemoteConfig
import kotlinx.coroutines.tasks.await
import javax.inject.Inject

private const val ON_SERIVCE = "ON_SERVICE"

class FirebaseRepository @Inject constructor(
private val remoteConfig: FirebaseRemoteConfig
) {

suspend fun getService(): ServiceState {
val serviceState = ServiceState("", "")
remoteConfig.fetchAndActivate().await()
serviceState.state = remoteConfig.getString(SERVICE_STATE)
if (serviceState.state != ON_SERIVCE)
serviceState.msg = remoteConfig.getString(SERVICE_MESSAGE)
return serviceState
}
}
63 changes: 63 additions & 0 deletions app/src/main/java/campus/tech/kakao/map/service/FCMService.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package campus.tech.kakao.map.service

import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Intent
import android.os.Build
import androidx.core.app.NotificationCompat
import campus.tech.kakao.map.R
import campus.tech.kakao.map.view.splashscreen.SplashScreenActivity
import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.RemoteMessage

private const val CUSTOM_HEADER = "[Foreground] "
class FCMService : FirebaseMessagingService() {
companion object {
private const val NOTIFICATION_ID = 0
private const val CHANNEL_ID = "main_default_channel"
private const val CHANNEL_NAME = "main channelName"
}

private lateinit var notificationManager: NotificationManager

override fun onMessageReceived(remoteMessage: RemoteMessage) {
remoteMessage.notification?.let {
val customTitle = CUSTOM_HEADER + it.title
showNotification(customTitle, it.body)
}
}

private fun createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel(
CHANNEL_ID,
CHANNEL_NAME,
NotificationManager.IMPORTANCE_DEFAULT
)
notificationManager.createNotificationChannel(channel)
}
}

private fun showNotification(title: String?, message: String?) {
notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
createNotificationChannel()

val intent = Intent(this, SplashScreenActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK)

val pendingIntent = PendingIntent.getActivity(
this, 0, intent, PendingIntent.FLAG_IMMUTABLE
)

val notificationBuilder = NotificationCompat.Builder(this, CHANNEL_ID)
.setSmallIcon(R.drawable.map)
.setContentTitle(title)
.setContentText(message)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setContentIntent(pendingIntent)
.setAutoCancel(true)

notificationManager.notify(NOTIFICATION_ID, notificationBuilder.build())
}
}
3 changes: 2 additions & 1 deletion app/src/main/java/campus/tech/kakao/map/view/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@ import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import campus.tech.kakao.map.R
import campus.tech.kakao.map.view.kakaomap.KakaoMapActivity
import campus.tech.kakao.map.view.splashscreen.SplashScreenActivity

class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val intent = Intent(this, KakaoMapActivity::class.java)
val intent = Intent(this, SplashScreenActivity::class.java)
startActivity(intent)
finish()
}
Expand Down
Loading