Pause/Resume sync thread when app goes background/foreground

This commit is contained in:
ganfra
2018-10-17 15:20:26 +02:00
parent d9f1d3fc85
commit e7f9bf86c6
7 changed files with 74 additions and 12 deletions

View File

@ -1,12 +1,13 @@
package im.vector.matrix.android.api
import android.arch.lifecycle.ProcessLifecycleOwner
import android.content.Context
import com.evernote.android.job.JobManager
import im.vector.matrix.android.api.auth.Authenticator
import im.vector.matrix.android.api.session.Session
import im.vector.matrix.android.internal.auth.AuthModule
import im.vector.matrix.android.internal.di.MatrixModule
import im.vector.matrix.android.internal.di.NetworkModule
import im.vector.matrix.android.internal.util.BackgroundDetectionObserver
import io.realm.Realm
import org.koin.standalone.KoinComponent
import org.koin.standalone.StandAloneContext.loadKoinModules
@ -16,16 +17,17 @@ import org.koin.standalone.inject
class Matrix(matrixOptions: MatrixOptions) : KoinComponent {
private val authenticator by inject<Authenticator>()
private val backgroundDetectionObserver by inject<BackgroundDetectionObserver>()
var currentSession: Session? = null
init {
Realm.init(matrixOptions.context)
JobManager.create(matrixOptions.context)
val matrixModule = MatrixModule(matrixOptions)
val networkModule = NetworkModule()
val authModule = AuthModule()
loadKoinModules(listOf(matrixModule, networkModule, authModule))
ProcessLifecycleOwner.get().lifecycle.addObserver(backgroundDetectionObserver)
}
fun authenticator(): Authenticator {

View File

@ -2,6 +2,7 @@ package im.vector.matrix.android.internal.di
import im.vector.matrix.android.api.MatrixOptions
import im.vector.matrix.android.api.thread.MainThreadExecutor
import im.vector.matrix.android.internal.util.BackgroundDetectionObserver
import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.IO
@ -22,5 +23,10 @@ class MatrixModule(private val options: MatrixOptions) : Module {
single {
MatrixCoroutineDispatchers(io = Dispatchers.IO, computation = Dispatchers.IO, main = MainThreadExecutor().asCoroutineDispatcher())
}
single {
BackgroundDetectionObserver()
}
}.invoke()
}

View File

@ -34,7 +34,7 @@ class SyncModule : Module {
}
scope(DefaultSession.SCOPE) {
SyncThread(get(), get(), get())
SyncThread(get(), get(), get(), get())
}

View File

@ -7,6 +7,7 @@ import im.vector.matrix.android.internal.events.sync.SyncRequest
import im.vector.matrix.android.internal.events.sync.SyncTokenStore
import im.vector.matrix.android.internal.events.sync.data.SyncResponse
import im.vector.matrix.android.internal.network.NetworkConnectivityChecker
import im.vector.matrix.android.internal.util.BackgroundDetectionObserver
import timber.log.Timber
import java.util.concurrent.CountDownLatch
@ -14,8 +15,9 @@ private const val RETRY_WAIT_TIME_MS = 10_000L
class SyncThread(private val syncRequest: SyncRequest,
private val networkConnectivityChecker: NetworkConnectivityChecker,
private val syncTokenStore: SyncTokenStore
) : Thread(), NetworkConnectivityChecker.Listener {
private val syncTokenStore: SyncTokenStore,
private val backgroundDetectionObserver: BackgroundDetectionObserver
) : Thread(), NetworkConnectivityChecker.Listener, BackgroundDetectionObserver.Listener {
enum class State {
IDLE,
@ -63,8 +65,9 @@ class SyncThread(private val syncRequest: SyncRequest,
override fun run() {
Timber.v("Start syncing...")
state = State.RUNNING
networkConnectivityChecker.register(this)
backgroundDetectionObserver.register(this)
state = State.RUNNING
while (state != State.KILLING) {
if (!networkConnectivityChecker.isConnected() || state == State.PAUSED) {
Timber.v("Waiting...")
@ -94,6 +97,7 @@ class SyncThread(private val syncRequest: SyncRequest,
}
Timber.v("Sync killed")
state = State.KILLED
backgroundDetectionObserver.unregister(this)
networkConnectivityChecker.unregister(this)
}
@ -103,6 +107,15 @@ class SyncThread(private val syncRequest: SyncRequest,
}
}
override fun onMoveToForeground() {
restart()
}
override fun onMoveToBackground() {
pause()
}
}

View File

@ -0,0 +1,46 @@
package im.vector.matrix.android.internal.util
import android.arch.lifecycle.Lifecycle
import android.arch.lifecycle.LifecycleObserver
import android.arch.lifecycle.OnLifecycleEvent
import timber.log.Timber
/**
* To be attached to ProcessLifecycleOwner lifecycle
*/
class BackgroundDetectionObserver : LifecycleObserver {
var isIsBackground: Boolean = false
private set
private
val listeners = ArrayList<Listener>()
fun register(listener: Listener) {
listeners.add(listener)
}
fun unregister(listener: Listener) {
listeners.remove(listener)
}
@OnLifecycleEvent(Lifecycle.Event.ON_START)
fun onMoveToForeground() {
Timber.d("App returning to foreground…")
isIsBackground = false
listeners.forEach { it.onMoveToForeground() }
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
fun onMoveToBackground() {
Timber.d("App going to background…")
isIsBackground = true
listeners.forEach { it.onMoveToBackground() }
}
interface Listener {
fun onMoveToForeground()
fun onMoveToBackground()
}
}