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

[feature/apply-lifecycle-service] Service에 Lifecycle 적용하기 #671

Merged
merged 2 commits into from
Apr 19, 2024
Merged
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package org.sopt.official.config.messaging

import android.os.Handler
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.LifecycleRegistry

class ServiceLifecycleDispatcher(provider: LifecycleOwner) {
private val registry: LifecycleRegistry = LifecycleRegistry(provider)
private val handler: Handler
private var lastDispatchRunnable: DispatchRunnable? = null

init {
@Suppress("DEPRECATION")
handler = Handler()
}
l2hyunwoo marked this conversation as resolved.
Show resolved Hide resolved

private fun postDispatchRunnable(event: Lifecycle.Event) {
lastDispatchRunnable?.run()
lastDispatchRunnable = DispatchRunnable(registry, event)
handler.postAtFrontOfQueue(lastDispatchRunnable!!)
}

/**
* Must be a first call in [Service.onCreate] method, even before super.onCreate call.
*/
fun onServicePreSuperOnCreate() {
postDispatchRunnable(Lifecycle.Event.ON_CREATE)
}

/**
* Must be a first call in [Service.onBind] method, even before super.onBind
* call.
*/
fun onServicePreSuperOnBind() {
postDispatchRunnable(Lifecycle.Event.ON_START)
}

/**
* Must be a first call in [Service.onStart] or
* [Service.onStartCommand] methods, even before
* a corresponding super call.
*/
fun onServicePreSuperOnStart() {
postDispatchRunnable(Lifecycle.Event.ON_START)
}

/**
* Must be a first call in [Service.onDestroy] method, even before super.OnDestroy
* call.
*/
fun onServicePreSuperOnDestroy() {
postDispatchRunnable(Lifecycle.Event.ON_STOP)
postDispatchRunnable(Lifecycle.Event.ON_DESTROY)
}

/**
* [Lifecycle] for the given [LifecycleOwner]
*/
val lifecycle: Lifecycle
get() = registry

internal class DispatchRunnable(
private val registry: LifecycleRegistry,
val event: Lifecycle.Event
) : Runnable {
private var wasExecuted = false

override fun run() {
if (!wasExecuted) {
registry.handleLifecycleEvent(event)
wasExecuted = true
}
}
}
l2hyunwoo marked this conversation as resolved.
Show resolved Hide resolved
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,17 @@ package org.sopt.official.config.messaging
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.os.Build
import androidx.annotation.CallSuper
import androidx.core.app.NotificationCompat
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.lifecycleScope
import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.RemoteMessage
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.launch
import org.sopt.official.R
import org.sopt.official.auth.model.UserStatus
Expand All @@ -44,20 +46,36 @@ import org.sopt.official.feature.notification.SchemeActivity
import org.sopt.official.network.persistence.SoptDataStore

@AndroidEntryPoint
class SoptFirebaseMessagingService : FirebaseMessagingService() {
class SoptFirebaseMessagingService : FirebaseMessagingService(), LifecycleOwner {

@Inject
lateinit var dataStore: SoptDataStore

@Inject
lateinit var registerPushTokenUseCase: RegisterPushTokenUseCase

private val job = SupervisorJob()
private val scope = CoroutineScope(Dispatchers.IO + job)
private val dispatcher = ServiceLifecycleDispatcher(this)

override val lifecycle: Lifecycle
get() = dispatcher.lifecycle

@CallSuper
override fun onCreate() {
dispatcher.onServicePreSuperOnCreate()
super.onCreate()
}

@Deprecated("Deprecated in Java")
@Suppress("DEPRECATION")
@CallSuper
override fun onStart(intent: Intent?, startId: Int) {
dispatcher.onServicePreSuperOnStart()
super.onStart(intent, startId)
}

override fun onNewToken(token: String) {
if (dataStore.userStatus == UserStatus.UNAUTHENTICATED.name) return
scope.launch {
lifecycleScope.launch {
dataStore.pushToken = token
registerPushTokenUseCase.invoke(token)
}
Expand Down Expand Up @@ -118,12 +136,13 @@ class SoptFirebaseMessagingService : FirebaseMessagingService() {
)
}

companion object {
const val NOTIFICATION_CHANNEL_ID = "SOPT"
}

@CallSuper
override fun onDestroy() {
dispatcher.onServicePreSuperOnDestroy()
super.onDestroy()
job.cancel()
}

companion object {
const val NOTIFICATION_CHANNEL_ID = "SOPT"
}
}