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

@ -45,7 +45,6 @@ dependencies {
def support_version = '28.0.0'
def moshi_version = '1.7.0'
def lifecycle_version = "1.1.1"
def work_version = "1.0.0-alpha10"

implementation fileTree(dir: 'libs', include: ['*.aar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
@ -65,7 +64,6 @@ dependencies {
implementation 'com.squareup.okhttp3:logging-interceptor:3.10.0'
implementation 'com.squareup.okio:okio:1.15.0'
implementation 'com.novoda:merlin:1.1.6'

implementation 'com.google.code.gson:gson:2.8.5'
implementation "com.squareup.moshi:moshi-adapters:$moshi_version"
kapt "com.squareup.moshi:moshi-kotlin-codegen:$moshi_version"
@ -73,10 +71,7 @@ dependencies {
// Paging
implementation "android.arch.paging:runtime:1.0.1"

// Worker
implementation "android.arch.work:work-runtime-ktx:$work_version"
implementation 'com.evernote:android-job:1.2.6'

// FP
implementation "io.arrow-kt:arrow-core:$arrow_version"

// DI

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()
}

}