Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
89c0c12
feat: 알림 뷰 xml 구현
m6z1 Jan 22, 2025
89c2769
feat: 알림 설정 뷰 토글 상태 로직 구현
m6z1 Jan 22, 2025
0185469
feat: 알림 권한 없을 경우 권한 설정 이동 다이얼로그 구현
m6z1 Jan 23, 2025
fa6d8a1
feat: 변경된 fcm 토큰 저장 api 수정
m6z1 Jan 24, 2025
dc90ed0
Merge branch 'develop' of https://github.com/Team-WSS/WSS-Android int…
m6z1 Jan 24, 2025
0325c73
feat: 토큰 만료 시 업데이트 로직 구현
m6z1 Jan 24, 2025
b6fa864
build: 불필요한 파일 제거
m6z1 Jan 24, 2025
bab3f81
feat: 뷰에서 완료 버튼 삭제
m6z1 Jan 24, 2025
3f0da6c
build: 불필요한 코드 제거
m6z1 Jan 24, 2025
3237f4f
feat: 알림 수신여부 api 연동
m6z1 Jan 24, 2025
9656b1d
fix: fcm service에 repository 의존성 수정
m6z1 Jan 24, 2025
69fdd3a
refactor: 토글 버튼 디바운스 적용
m6z1 Jan 24, 2025
7f0e34e
fix: 알림 수신여부 초기에 null 값 반환하는 에러 수정
m6z1 Jan 24, 2025
3219bc8
feat: 토글 버튼 디자인 반영
m6z1 Jan 25, 2025
b37a2db
Merge branch 'develop' of https://github.com/Team-WSS/WSS-Android int…
m6z1 Jan 25, 2025
956d937
feat: 푸시 알림 클릭 시 notificationId 값 전달
m6z1 Jan 25, 2025
5b4b39d
build: ktlint 포맷팅
m6z1 Jan 25, 2025
c91565b
build: ktlint 포맷팅
m6z1 Jan 25, 2025
f1d6be4
refactor: 푸시알림 수신 여부 네이밍 notificationPushEnabled로 통일
m6z1 Jan 25, 2025
51cb960
refactor: fcm 토큰 저장 로직 수정
m6z1 Jan 25, 2025
5757e1a
build: 불필요한 import 제거
m6z1 Jan 25, 2025
75997b7
fix: 기존 토큰과 다를 경우 로컬에도 fcm 토큰값 업데이트
m6z1 Jan 25, 2025
bc585bb
fix: 홈 화면 읽어야 할 알림 있을 때 아이콘 수정
m6z1 Jan 25, 2025
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
4 changes: 4 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,10 @@
android:name=".ui.userStorage.UserStorageActivity"
android:exported="false"
android:screenOrientation="portrait" />
<activity
android:name=".ui.notificationSetting.NotificationSettingActivity"
android:exported="false"
android:screenOrientation="portrait" />
</application>

</manifest>
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,20 @@ import androidx.core.app.NotificationCompat
import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.RemoteMessage
import com.into.websoso.R
import com.into.websoso.data.repository.PushMessageRepository
import com.into.websoso.ui.feedDetail.FeedDetailActivity
import com.into.websoso.ui.main.MainActivity
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import javax.inject.Inject

@AndroidEntryPoint
class WSSFirebaseMessagingService : FirebaseMessagingService() {
@Inject
Copy link
Member

Choose a reason for hiding this comment

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

a: 생성자주입 안받는 이유가 있나요 ?

Copy link
Member Author

Choose a reason for hiding this comment

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

생성자 주입하면 푸시 알림 왔을 때 여기서 터지더라구요

lateinit var pushMessageRepository: PushMessageRepository

override fun onMessageReceived(message: RemoteMessage) {
super.onMessageReceived(message)

Expand All @@ -22,9 +32,13 @@ class WSSFirebaseMessagingService : FirebaseMessagingService() {
val title = receivedData["title"] ?: DEFAULT_TITLE
val body = receivedData["body"] ?: DEFAULT_BODY
val feedId = receivedData["feedId"]?.toLongOrNull() ?: return
val notificationId = receivedData["notificationId"]?.toLongOrNull() ?: return

setupNotificationChannel()
val pendingIntent = createPendingIntent(feedId)
val pendingIntent = createPendingIntent(
feedId,
notificationId,
)
showNotification(title, body, pendingIntent)
}

Expand All @@ -41,9 +55,12 @@ class WSSFirebaseMessagingService : FirebaseMessagingService() {
notificationManager.createNotificationChannel(channel)
}

private fun createPendingIntent(feedId: Long): PendingIntent {
private fun createPendingIntent(
feedId: Long,
notificationId: Long,
): PendingIntent {
val mainIntent = MainActivity.getIntent(this)
val detailIntent = FeedDetailActivity.getIntent(this, feedId)
val detailIntent = FeedDetailActivity.getIntent(this, feedId, notificationId)

return TaskStackBuilder.create(this).run {
addNextIntent(mainIntent)
Expand Down Expand Up @@ -73,6 +90,12 @@ class WSSFirebaseMessagingService : FirebaseMessagingService() {

override fun onNewToken(token: String) {
super.onNewToken(token)

CoroutineScope(Dispatchers.IO).launch {
runCatching {
pushMessageRepository.updateUserFCMToken(token)
}
}
}

companion object {
Expand Down
7 changes: 7 additions & 0 deletions app/src/main/java/com/into/websoso/data/di/ApiModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import com.into.websoso.data.remote.api.FeedApi
import com.into.websoso.data.remote.api.KeywordApi
import com.into.websoso.data.remote.api.NotificationApi
import com.into.websoso.data.remote.api.NovelApi
import com.into.websoso.data.remote.api.PushMessageApi
import com.into.websoso.data.remote.api.UserApi
import com.into.websoso.data.remote.api.UserNovelApi
import com.into.websoso.data.remote.api.VersionApi
Expand Down Expand Up @@ -74,4 +75,10 @@ object ApiModule {
fun provideVersionApi(
@Secured retrofit: Retrofit,
): VersionApi = retrofit.create(VersionApi::class.java)

@Provides
@Singleton
fun providePushMessageApi(
@Secured retrofit: Retrofit,
): PushMessageApi = retrofit.create(PushMessageApi::class.java)
}
14 changes: 12 additions & 2 deletions app/src/main/java/com/into/websoso/data/di/RepositoryModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ import androidx.datastore.preferences.core.Preferences
import com.into.websoso.data.remote.api.AuthApi
import com.into.websoso.data.remote.api.FeedApi
import com.into.websoso.data.remote.api.NovelApi
import com.into.websoso.data.remote.api.PushMessageApi
import com.into.websoso.data.remote.api.UserApi
import com.into.websoso.data.remote.api.VersionApi
import com.into.websoso.data.repository.AuthRepository
import com.into.websoso.data.repository.FeedRepository
import com.into.websoso.data.repository.NovelRepository
import com.into.websoso.data.repository.PushMessageRepository
import com.into.websoso.data.repository.UserRepository
import com.into.websoso.data.repository.VersionRepository
import dagger.Module
Expand All @@ -22,7 +24,6 @@ import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
object RepositoryModule {

@Provides
@Singleton
fun provideFeedRepository(feedApi: FeedApi): FeedRepository = FeedRepository(feedApi)
Expand All @@ -48,4 +49,13 @@ object RepositoryModule {
@Provides
@Singleton
fun provideVersionRepository(versionApi: VersionApi): VersionRepository = VersionRepository(versionApi)
}

@Provides
@Singleton
fun providePushMessageRepository(
userRepository: UserRepository,
authRepository: AuthRepository,
userStorage: DataStore<Preferences>,
pushMessageApi: PushMessageApi,
): PushMessageRepository = PushMessageRepository(userRepository, authRepository, userStorage, pushMessageApi)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.into.websoso.data.remote.api

import com.into.websoso.data.remote.request.NotificationPushEnabledRequestDto
import com.into.websoso.data.remote.response.NotificationPushEnabledResponseDto
import retrofit2.http.Body
import retrofit2.http.GET
import retrofit2.http.POST

interface PushMessageApi {
@GET("users/push-settings")
suspend fun getUserPushEnabled(): NotificationPushEnabledResponseDto

@POST("users/push-settings")
suspend fun postUserPushEnabled(
@Body notificationPushEnabledRequestDto: NotificationPushEnabledRequestDto,
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package com.into.websoso.data.remote.api

import com.into.websoso.data.remote.request.UserInfoRequestDto
import com.into.websoso.data.remote.request.UserProfileEditRequestDto
import com.into.websoso.data.remote.request.UserProfileRequestDto
import com.into.websoso.data.remote.request.UserProfileStatusRequestDto
import com.into.websoso.data.remote.response.BlockedUsersResponseDto
import com.into.websoso.data.remote.response.GenrePreferenceResponseDto
Expand Down Expand Up @@ -92,11 +91,6 @@ interface UserApi {
@Path("userId") userId: Long,
): OtherUserProfileResponseDto

@POST("users/profile")
suspend fun postUserProfile(
@Body userProfileRequestDto: UserProfileRequestDto,
)

@GET("users/{userId}/novels")
suspend fun getUserStorage(
@Path("userId") userId: Long,
Expand All @@ -112,4 +106,4 @@ interface UserApi {
@Query("lastFeedId") lastFeedId: Long,
@Query("size") size: Int,
): UserFeedsResponseDto
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,6 @@ import kotlinx.serialization.Serializable
data class FCMTokenRequestDto(
@SerialName("fcmToken")
val fcmToken: String,
@SerialName("deviceIdentifier")
val deviceIdentifier: String,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.into.websoso.data.remote.request

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class NotificationPushEnabledRequestDto(
@SerialName("isPushEnabled")
val isPushEnabled: Boolean,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.into.websoso.data.remote.response

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class NotificationPushEnabledResponseDto(
@SerialName("isPushEnabled")
val isPushEnabled: Boolean,
)
Original file line number Diff line number Diff line change
Expand Up @@ -108,10 +108,16 @@ class AuthRepository @Inject constructor(
this.isAutoLogin = isAutoLogin
}

suspend fun saveFCMToken(fcmToken: String) {
suspend fun saveFCMToken(
fcmToken: String,
deviceIdentifier: String,
) {
authApi.postFCMToken(
authorization = "Bearer $accessToken",
FCMTokenRequestDto(fcmToken = fcmToken),
FCMTokenRequestDto(
fcmToken = fcmToken,
deviceIdentifier = deviceIdentifier,
),
)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package com.into.websoso.data.repository

import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.booleanPreferencesKey
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.stringPreferencesKey
import com.into.websoso.data.remote.api.PushMessageApi
import com.into.websoso.data.remote.request.NotificationPushEnabledRequestDto
import kotlinx.coroutines.flow.first
import javax.inject.Inject

class PushMessageRepository
@Inject
constructor(
private val userRepository: UserRepository,
private val authRepository: AuthRepository,
private val userStorage: DataStore<Preferences>,
private val pushMessageApi: PushMessageApi,
) {
suspend fun updateUserFCMToken(fcmToken: String) {
val storedToken = fetchUserFCMToken()
if (fcmToken == storedToken) {
return
}

saveUserFCMToken(fcmToken)
}

suspend fun saveUserFCMToken(fcmToken: String) {
userStorage.edit { preferences ->
preferences[USER_FCM_TOKEN_KEY] = fcmToken
}

saveUserFCMTokenToRemote(fcmToken)
}

private suspend fun saveUserFCMTokenToRemote(fcmToken: String) {
val deviceIdentifier = userRepository.fetchUserDeviceIdentifier()
authRepository.saveFCMToken(fcmToken, deviceIdentifier)
}

private suspend fun fetchUserFCMToken(): String {
val preferences = userStorage.data.first()
return preferences[USER_FCM_TOKEN_KEY] ?: ""
}

suspend fun saveNotificationPermissionFirstLaunched(value: Boolean) {
userStorage.edit { preferences ->
preferences[NOTIFICATION_PERMISSION_FIRST_LAUNCHED_KEY] = value
}
}

suspend fun fetchNotificationPermissionFirstLaunched() =
userStorage.data.first()[NOTIFICATION_PERMISSION_FIRST_LAUNCHED_KEY] ?: true

suspend fun fetchUserPushEnabled(): Boolean = pushMessageApi.getUserPushEnabled().isPushEnabled

suspend fun saveUserPushEnabled(isEnabled: Boolean) {
pushMessageApi.postUserPushEnabled(
notificationPushEnabledRequestDto = NotificationPushEnabledRequestDto(
isPushEnabled = isEnabled,
),
)
}

companion object {
val USER_FCM_TOKEN_KEY = stringPreferencesKey("USER_FCM_TOKEN")
val NOTIFICATION_PERMISSION_FIRST_LAUNCHED_KEY =
booleanPreferencesKey("NOTIFICATION_PERMISSION_FIRST_LAUNCHED")
}
}

This file was deleted.

Loading
Loading