diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 13672dc..c40aecd 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -3,6 +3,8 @@
xmlns:tools="http://schemas.android.com/tools">
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/java/kr/co/vividnext/sodalive/common/Constants.kt b/app/src/main/java/kr/co/vividnext/sodalive/common/Constants.kt
index a0bd7ed..b700cbf 100644
--- a/app/src/main/java/kr/co/vividnext/sodalive/common/Constants.kt
+++ b/app/src/main/java/kr/co/vividnext/sodalive/common/Constants.kt
@@ -8,12 +8,14 @@ object Constants {
const val PREF_IS_ADULT = "pref_is_adult"
const val PREF_NICKNAME = "pref_nickname"
const val PREF_USER_ROLE = "pref_user_role"
+ const val PREF_PUSH_TOKEN = "pref_push_token"
const val PREF_PROFILE_IMAGE = "pref_profile_image"
const val EXTRA_DATA = "extra_data"
const val EXTRA_TERMS = "extra_terms"
const val EXTRA_USER_ID = "extra_user_id"
const val EXTRA_ROOM_ID = "extra_room_id"
+ const val EXTRA_MESSAGE_ID = "extra_message_id"
- const val EXTRA_AUDIO_CONTENT_ID = "extra_audio_content_id"
+ const val EXTRA_CONTENT_ID = "extra_content_id"
}
diff --git a/app/src/main/java/kr/co/vividnext/sodalive/common/SharedPreferenceManager.kt b/app/src/main/java/kr/co/vividnext/sodalive/common/SharedPreferenceManager.kt
index 7d1e00c..60bbe3f 100644
--- a/app/src/main/java/kr/co/vividnext/sodalive/common/SharedPreferenceManager.kt
+++ b/app/src/main/java/kr/co/vividnext/sodalive/common/SharedPreferenceManager.kt
@@ -92,4 +92,10 @@ object SharedPreferenceManager {
set(value) {
sharedPreferences[Constants.PREF_IS_ADULT] = value
}
+
+ var pushToken: String
+ get() = sharedPreferences[Constants.PREF_PUSH_TOKEN, ""]
+ set(value) {
+ sharedPreferences[Constants.PREF_PUSH_TOKEN] = value
+ }
}
diff --git a/app/src/main/java/kr/co/vividnext/sodalive/fcm/SodaFirebaseMessagingService.kt b/app/src/main/java/kr/co/vividnext/sodalive/fcm/SodaFirebaseMessagingService.kt
new file mode 100644
index 0000000..7bf4ec9
--- /dev/null
+++ b/app/src/main/java/kr/co/vividnext/sodalive/fcm/SodaFirebaseMessagingService.kt
@@ -0,0 +1,89 @@
+package kr.co.vividnext.sodalive.fcm
+
+import android.app.NotificationChannel
+import android.app.NotificationManager
+import android.app.PendingIntent
+import android.content.Context
+import android.content.Intent
+import android.media.RingtoneManager
+import android.os.Build
+import androidx.core.app.NotificationCompat
+import com.google.firebase.messaging.FirebaseMessagingService
+import com.google.firebase.messaging.RemoteMessage
+import kr.co.vividnext.sodalive.R
+import kr.co.vividnext.sodalive.common.Constants
+import kr.co.vividnext.sodalive.common.SharedPreferenceManager
+import kr.co.vividnext.sodalive.splash.SplashActivity
+
+class SodaFirebaseMessagingService : FirebaseMessagingService() {
+ override fun onMessageReceived(remoteMessage: RemoteMessage) {
+ if (SharedPreferenceManager.token.isNotBlank()) {
+ when {
+ remoteMessage.data.isNotEmpty() -> {
+ sendNotification(remoteMessage.data)
+ }
+ }
+ }
+ }
+
+ override fun onNewToken(token: String) {
+ SharedPreferenceManager.pushToken = token
+ }
+
+ private fun sendNotification(messageData: Map) {
+ val notificationChannelId = getString(R.string.default_notification_channel_id)
+ val defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
+ val notificationManager =
+ getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
+
+ // Since android Oreo notification channel is needed.
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ val channel =
+ NotificationChannel(
+ notificationChannelId,
+ getString(R.string.app_name),
+ NotificationManager.IMPORTANCE_HIGH
+ )
+ notificationManager.createNotificationChannel(channel)
+ }
+
+ val intent = Intent(this, SplashActivity::class.java)
+ intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
+ intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)
+
+ val roomId = messageData["room_id"]
+ if (roomId != null) {
+ intent.putExtra(Constants.EXTRA_ROOM_ID, roomId.toLong())
+ }
+
+ val socdocId = messageData["message_id"]
+ if (socdocId != null) {
+ intent.putExtra(Constants.EXTRA_MESSAGE_ID, socdocId.toLong())
+ }
+
+ val audioContentId = messageData["content_id"]
+ if (audioContentId != null) {
+ intent.putExtra(Constants.EXTRA_CONTENT_ID, audioContentId.toLong())
+ }
+
+ val pendingIntent =
+ PendingIntent.getActivity(
+ this,
+ System.currentTimeMillis().toInt(),
+ intent,
+ PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
+ )
+
+ val notificationBuilder = NotificationCompat.Builder(this, notificationChannelId)
+ .setContentTitle(messageData["title"])
+ .setContentText(messageData["message"])
+ .setSound(defaultSoundUri)
+ .setAutoCancel(true)
+ .setContentIntent(pendingIntent)
+
+ val bigTextStyle = NotificationCompat.BigTextStyle(notificationBuilder)
+ bigTextStyle.bigText(messageData["message"])
+
+ notificationManager.notify(System.currentTimeMillis().toInt(), notificationBuilder.build())
+ }
+}
diff --git a/app/src/main/java/kr/co/vividnext/sodalive/main/MainActivity.kt b/app/src/main/java/kr/co/vividnext/sodalive/main/MainActivity.kt
index c9be4e4..7b9d746 100644
--- a/app/src/main/java/kr/co/vividnext/sodalive/main/MainActivity.kt
+++ b/app/src/main/java/kr/co/vividnext/sodalive/main/MainActivity.kt
@@ -1,12 +1,19 @@
package kr.co.vividnext.sodalive.main
+import android.Manifest
import android.content.res.ColorStateList
+import android.os.Build
import android.os.Bundle
import androidx.core.content.ContextCompat
import androidx.core.content.res.ResourcesCompat
+import com.google.firebase.messaging.FirebaseMessaging
+import com.gun0912.tedpermission.PermissionListener
+import com.gun0912.tedpermission.normal.TedPermission
+import com.orhanobut.logger.Logger
import kr.co.vividnext.sodalive.R
import kr.co.vividnext.sodalive.base.BaseActivity
import kr.co.vividnext.sodalive.common.LoadingDialog
+import kr.co.vividnext.sodalive.common.SharedPreferenceManager
import kr.co.vividnext.sodalive.content.main.ContentMainFragment
import kr.co.vividnext.sodalive.databinding.ActivityMainBinding
import kr.co.vividnext.sodalive.databinding.ItemMainTabBinding
@@ -27,8 +34,8 @@ class MainActivity : BaseActivity(ActivityMainBinding::infl
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
-
- setupBottomTabLayout()
+ checkPermissions()
+ pushTokenUpdate()
getMemberInfo()
}
@@ -47,6 +54,8 @@ class MainActivity : BaseActivity(ActivityMainBinding::infl
isNotifiedMessage
)
}
+
+ setupBottomTabLayout()
}
private fun setupBottomTabLayout() {
@@ -196,6 +205,41 @@ class MainActivity : BaseActivity(ActivityMainBinding::infl
fragmentTransaction.commitNow()
}
+ private fun checkPermissions() {
+ val permissions = mutableListOf(Manifest.permission.RECORD_AUDIO)
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+ permissions.add(Manifest.permission.POST_NOTIFICATIONS)
+ }
+
+ TedPermission.create()
+ .setPermissionListener(object : PermissionListener {
+ override fun onPermissionGranted() {
+ }
+
+ override fun onPermissionDenied(deniedPermissions: MutableList?) {
+ }
+ })
+ .setDeniedMessage(R.string.record_audio_permission_denied_message)
+ .setPermissions(*permissions.toTypedArray())
+ .check()
+ }
+
+ private fun pushTokenUpdate() {
+ FirebaseMessaging.getInstance().token.addOnCompleteListener {
+ if (!it.isSuccessful) {
+ Logger.v("Fetching FCM registration token failed", it.exception)
+ return@addOnCompleteListener
+ }
+
+ val pushToken = it.result
+ if (pushToken != null) {
+ SharedPreferenceManager.pushToken = pushToken
+ viewModel.pushTokenUpdate(pushToken)
+ }
+ }
+ }
+
private fun getMemberInfo() {
viewModel.getMemberInfo {
notificationSettingsDialog.show(screenWidth)
diff --git a/app/src/main/java/kr/co/vividnext/sodalive/main/MainViewModel.kt b/app/src/main/java/kr/co/vividnext/sodalive/main/MainViewModel.kt
index 5824a03..2996929 100644
--- a/app/src/main/java/kr/co/vividnext/sodalive/main/MainViewModel.kt
+++ b/app/src/main/java/kr/co/vividnext/sodalive/main/MainViewModel.kt
@@ -60,6 +60,20 @@ class MainViewModel(
)
}
+ fun pushTokenUpdate(pushToken: String) {
+ val request = PushTokenUpdateRequest(
+ pushToken = pushToken
+ )
+
+ compositeDisposable.add(
+ userRepository
+ .updatePushToken(request, "Bearer ${SharedPreferenceManager.token}")
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe({}, {})
+ )
+ }
+
fun getMemberInfo(showNotificationSettingsDialog: () -> Unit) {
compositeDisposable.add(
userRepository.getMemberInfo(token = "Bearer ${SharedPreferenceManager.token}")
diff --git a/app/src/main/java/kr/co/vividnext/sodalive/main/PushTokenUpdateRequest.kt b/app/src/main/java/kr/co/vividnext/sodalive/main/PushTokenUpdateRequest.kt
new file mode 100644
index 0000000..877c55e
--- /dev/null
+++ b/app/src/main/java/kr/co/vividnext/sodalive/main/PushTokenUpdateRequest.kt
@@ -0,0 +1,8 @@
+package kr.co.vividnext.sodalive.main
+
+import com.google.gson.annotations.SerializedName
+
+data class PushTokenUpdateRequest(
+ @SerializedName("pushToken") val pushToken: String,
+ @SerializedName("container") val container: String = "aos"
+)
diff --git a/app/src/main/java/kr/co/vividnext/sodalive/splash/SplashActivity.kt b/app/src/main/java/kr/co/vividnext/sodalive/splash/SplashActivity.kt
index 8bbba0a..5943a88 100644
--- a/app/src/main/java/kr/co/vividnext/sodalive/splash/SplashActivity.kt
+++ b/app/src/main/java/kr/co/vividnext/sodalive/splash/SplashActivity.kt
@@ -145,7 +145,7 @@ class SplashActivity : BaseActivity(ActivitySplashBinding
)
} else if (audioContentIdString != null) {
bundleOf(
- Constants.EXTRA_AUDIO_CONTENT_ID to audioContentIdString.toLong()
+ Constants.EXTRA_CONTENT_ID to audioContentIdString.toLong()
)
} else {
null
diff --git a/app/src/main/java/kr/co/vividnext/sodalive/user/UserApi.kt b/app/src/main/java/kr/co/vividnext/sodalive/user/UserApi.kt
index e340a08..7e59ec3 100644
--- a/app/src/main/java/kr/co/vividnext/sodalive/user/UserApi.kt
+++ b/app/src/main/java/kr/co/vividnext/sodalive/user/UserApi.kt
@@ -2,6 +2,7 @@ package kr.co.vividnext.sodalive.user
import io.reactivex.rxjava3.core.Single
import kr.co.vividnext.sodalive.common.ApiResponse
+import kr.co.vividnext.sodalive.main.PushTokenUpdateRequest
import kr.co.vividnext.sodalive.settings.notification.GetMemberInfoResponse
import kr.co.vividnext.sodalive.settings.notification.UpdateNotificationSettingRequest
import kr.co.vividnext.sodalive.user.find_password.ForgotPasswordRequest
@@ -14,6 +15,7 @@ import retrofit2.http.GET
import retrofit2.http.Header
import retrofit2.http.Multipart
import retrofit2.http.POST
+import retrofit2.http.PUT
import retrofit2.http.Part
interface UserApi {
@@ -40,4 +42,10 @@ interface UserApi {
@Body request: UpdateNotificationSettingRequest,
@Header("Authorization") authHeader: String
): Single>
+
+ @PUT("/member/push-token/update")
+ fun updatePushToken(
+ @Body request: PushTokenUpdateRequest,
+ @Header("Authorization") authHeader: String
+ ): Single>
}
diff --git a/app/src/main/java/kr/co/vividnext/sodalive/user/UserRepository.kt b/app/src/main/java/kr/co/vividnext/sodalive/user/UserRepository.kt
index 19d15f3..1c34592 100644
--- a/app/src/main/java/kr/co/vividnext/sodalive/user/UserRepository.kt
+++ b/app/src/main/java/kr/co/vividnext/sodalive/user/UserRepository.kt
@@ -1,5 +1,6 @@
package kr.co.vividnext.sodalive.user
+import kr.co.vividnext.sodalive.main.PushTokenUpdateRequest
import kr.co.vividnext.sodalive.settings.notification.UpdateNotificationSettingRequest
import kr.co.vividnext.sodalive.user.find_password.ForgotPasswordRequest
import kr.co.vividnext.sodalive.user.login.LoginRequest
@@ -21,5 +22,10 @@ class UserRepository(private val userApi: UserApi) {
token: String
) = userApi.updateNotificationSettings(request, authHeader = token)
+ fun updatePushToken(
+ request: PushTokenUpdateRequest,
+ token: String
+ ) = userApi.updatePushToken(request, authHeader = token)
+
fun getMemberInfo(token: String) = userApi.getMemberInfo(authHeader = token)
}
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 6018d58..cca3ae8 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -1,3 +1,15 @@
소다라이브
+ 갤러리
+ 카메라
+ 선택
+ 갤러리 접근을 위해 미디어 권한을 허용해야 합니다.
+ 미디어 라이브러리가 비어있습니다.
+ 허용
+ 사진선택
+ 사용할 수 있는 카메라 앱이 없습니다.
+ soda_fcm_default_channel
+ [권한]에서 권한을 허용해 주시기 바랍니다.]]>
+ [권한]에서 권한을 허용해 주시기 바랍니다.]]>
+ 다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다.