mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2024-11-23 01:45:52 +03:00
Sync: use a foreground service for initialSync.
This commit is contained in:
parent
79ef055bfb
commit
5338f93852
18 changed files with 177 additions and 148 deletions
|
@ -44,3 +44,5 @@ sealed class Failure(cause: Throwable? = null) : Throwable(cause = cause) {
|
||||||
|
|
||||||
abstract class FeatureFailure : Failure()
|
abstract class FeatureFailure : Failure()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun Throwable.isTokenError() = this is Failure.ServerError && (this.error.code == MatrixError.UNKNOWN_TOKEN || this.error.code == MatrixError.MISSING_TOKEN)
|
||||||
|
|
|
@ -104,6 +104,11 @@ interface Session :
|
||||||
*/
|
*/
|
||||||
fun syncState(): LiveData<SyncState>
|
fun syncState(): LiveData<SyncState>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This methods return true if an initial sync has been processed
|
||||||
|
*/
|
||||||
|
fun hasAlreadySynced(): Boolean
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method allow to close a session. It does stop some services.
|
* This method allow to close a session. It does stop some services.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -24,7 +24,7 @@ import im.vector.matrix.android.api.MatrixCallback
|
||||||
interface CacheService {
|
interface CacheService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clear the whole cached data, except credentials. Once done, the session is closed and has to be opened again
|
* Clear the whole cached data, except credentials. Once done, the sync has to be restarted by the sdk user.
|
||||||
*/
|
*/
|
||||||
fun clearCache(callback: MatrixCallback<Unit>)
|
fun clearCache(callback: MatrixCallback<Unit>)
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
package im.vector.matrix.android.internal.network
|
package im.vector.matrix.android.internal.network
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import androidx.annotation.WorkerThread
|
||||||
import com.novoda.merlin.Merlin
|
import com.novoda.merlin.Merlin
|
||||||
import com.novoda.merlin.MerlinsBeard
|
import com.novoda.merlin.MerlinsBeard
|
||||||
import im.vector.matrix.android.internal.di.MatrixScope
|
import im.vector.matrix.android.internal.di.MatrixScope
|
||||||
|
@ -28,8 +29,8 @@ import kotlin.coroutines.resume
|
||||||
import kotlin.coroutines.suspendCoroutine
|
import kotlin.coroutines.suspendCoroutine
|
||||||
|
|
||||||
@MatrixScope
|
@MatrixScope
|
||||||
internal class NetworkConnectivityChecker @Inject constructor(context: Context,
|
internal class NetworkConnectivityChecker @Inject constructor(private val context: Context,
|
||||||
backgroundDetectionObserver: BackgroundDetectionObserver)
|
private val backgroundDetectionObserver: BackgroundDetectionObserver)
|
||||||
: BackgroundDetectionObserver.Listener {
|
: BackgroundDetectionObserver.Listener {
|
||||||
|
|
||||||
private val merlin = Merlin.Builder()
|
private val merlin = Merlin.Builder()
|
||||||
|
@ -37,19 +38,30 @@ internal class NetworkConnectivityChecker @Inject constructor(context: Context,
|
||||||
.withDisconnectableCallbacks()
|
.withDisconnectableCallbacks()
|
||||||
.build(context)
|
.build(context)
|
||||||
|
|
||||||
private val listeners = Collections.synchronizedSet(LinkedHashSet<Listener>())
|
private val merlinsBeard = MerlinsBeard.Builder().build(context)
|
||||||
|
|
||||||
// True when internet is available
|
private val listeners = Collections.synchronizedSet(LinkedHashSet<Listener>())
|
||||||
var hasInternetAccess = MerlinsBeard.Builder().build(context).isConnected
|
private var hasInternetAccess = merlinsBeard.isConnected
|
||||||
private set
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
backgroundDetectionObserver.register(this)
|
backgroundDetectionObserver.register(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true when internet is available
|
||||||
|
*/
|
||||||
|
@WorkerThread
|
||||||
|
fun hasInternetAccess(): Boolean {
|
||||||
|
// If we are in background we have unbound merlin, so we have to check
|
||||||
|
return if (backgroundDetectionObserver.isIsBackground) {
|
||||||
|
merlinsBeard.hasInternetAccess()
|
||||||
|
} else {
|
||||||
|
hasInternetAccess
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onMoveToForeground() {
|
override fun onMoveToForeground() {
|
||||||
merlin.bind()
|
merlin.bind()
|
||||||
|
|
||||||
merlin.registerDisconnectable {
|
merlin.registerDisconnectable {
|
||||||
if (hasInternetAccess) {
|
if (hasInternetAccess) {
|
||||||
Timber.v("On Disconnect")
|
Timber.v("On Disconnect")
|
||||||
|
@ -76,14 +88,17 @@ internal class NetworkConnectivityChecker @Inject constructor(context: Context,
|
||||||
merlin.unbind()
|
merlin.unbind()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// In background you won't get notification as merlin is unbound
|
||||||
suspend fun waitUntilConnected() {
|
suspend fun waitUntilConnected() {
|
||||||
if (hasInternetAccess) {
|
if (hasInternetAccess) {
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
|
Timber.v("Waiting for network...")
|
||||||
suspendCoroutine<Unit> { continuation ->
|
suspendCoroutine<Unit> { continuation ->
|
||||||
register(object : Listener {
|
register(object : Listener {
|
||||||
override fun onConnect() {
|
override fun onConnect() {
|
||||||
unregister(this)
|
unregister(this)
|
||||||
|
Timber.v("Connected to network...")
|
||||||
continuation.resume(Unit)
|
continuation.resume(Unit)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -44,6 +44,7 @@ import im.vector.matrix.android.api.session.sync.SyncState
|
||||||
import im.vector.matrix.android.api.session.user.UserService
|
import im.vector.matrix.android.api.session.user.UserService
|
||||||
import im.vector.matrix.android.internal.crypto.DefaultCryptoService
|
import im.vector.matrix.android.internal.crypto.DefaultCryptoService
|
||||||
import im.vector.matrix.android.internal.database.LiveEntityObserver
|
import im.vector.matrix.android.internal.database.LiveEntityObserver
|
||||||
|
import im.vector.matrix.android.internal.session.sync.SyncTokenStore
|
||||||
import im.vector.matrix.android.internal.session.sync.job.SyncThread
|
import im.vector.matrix.android.internal.session.sync.job.SyncThread
|
||||||
import im.vector.matrix.android.internal.session.sync.job.SyncWorker
|
import im.vector.matrix.android.internal.session.sync.job.SyncWorker
|
||||||
import org.greenrobot.eventbus.EventBus
|
import org.greenrobot.eventbus.EventBus
|
||||||
|
@ -72,6 +73,7 @@ internal class DefaultSession @Inject constructor(override val sessionParams: Se
|
||||||
private val secureStorageService: Lazy<SecureStorageService>,
|
private val secureStorageService: Lazy<SecureStorageService>,
|
||||||
private val syncThreadProvider: Provider<SyncThread>,
|
private val syncThreadProvider: Provider<SyncThread>,
|
||||||
private val contentUrlResolver: ContentUrlResolver,
|
private val contentUrlResolver: ContentUrlResolver,
|
||||||
|
private val syncTokenStore: SyncTokenStore,
|
||||||
private val contentUploadProgressTracker: ContentUploadStateTracker,
|
private val contentUploadProgressTracker: ContentUploadStateTracker,
|
||||||
private val initialSyncProgressService: Lazy<InitialSyncProgressService>,
|
private val initialSyncProgressService: Lazy<InitialSyncProgressService>,
|
||||||
private val homeServerCapabilitiesService: Lazy<HomeServerCapabilitiesService>)
|
private val homeServerCapabilitiesService: Lazy<HomeServerCapabilitiesService>)
|
||||||
|
@ -147,6 +149,10 @@ internal class DefaultSession @Inject constructor(override val sessionParams: Se
|
||||||
return getSyncThread().liveState()
|
return getSyncThread().liveState()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun hasAlreadySynced(): Boolean {
|
||||||
|
return syncTokenStore.getLastToken() != null
|
||||||
|
}
|
||||||
|
|
||||||
private fun getSyncThread(): SyncThread {
|
private fun getSyncThread(): SyncThread {
|
||||||
return syncThread ?: syncThreadProvider.get().also {
|
return syncThread ?: syncThreadProvider.get().also {
|
||||||
syncThread = it
|
syncThread = it
|
||||||
|
@ -156,17 +162,7 @@ internal class DefaultSession @Inject constructor(override val sessionParams: Se
|
||||||
override fun clearCache(callback: MatrixCallback<Unit>) {
|
override fun clearCache(callback: MatrixCallback<Unit>) {
|
||||||
stopSync()
|
stopSync()
|
||||||
stopAnyBackgroundSync()
|
stopAnyBackgroundSync()
|
||||||
cacheService.get().clearCache(object : MatrixCallback<Unit> {
|
cacheService.get().clearCache(callback)
|
||||||
override fun onSuccess(data: Unit) {
|
|
||||||
startSync(true)
|
|
||||||
callback.onSuccess(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onFailure(failure: Throwable) {
|
|
||||||
startSync(true)
|
|
||||||
callback.onFailure(failure)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||||
|
|
|
@ -46,6 +46,7 @@ import im.vector.matrix.android.internal.session.sync.job.SyncWorker
|
||||||
import im.vector.matrix.android.internal.session.user.UserModule
|
import im.vector.matrix.android.internal.session.user.UserModule
|
||||||
import im.vector.matrix.android.internal.session.user.accountdata.AccountDataModule
|
import im.vector.matrix.android.internal.session.user.accountdata.AccountDataModule
|
||||||
import im.vector.matrix.android.internal.task.TaskExecutor
|
import im.vector.matrix.android.internal.task.TaskExecutor
|
||||||
|
import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
|
||||||
|
|
||||||
@Component(dependencies = [MatrixComponent::class],
|
@Component(dependencies = [MatrixComponent::class],
|
||||||
modules = [
|
modules = [
|
||||||
|
@ -69,6 +70,8 @@ import im.vector.matrix.android.internal.task.TaskExecutor
|
||||||
@SessionScope
|
@SessionScope
|
||||||
internal interface SessionComponent {
|
internal interface SessionComponent {
|
||||||
|
|
||||||
|
fun coroutineDispatchers(): MatrixCoroutineDispatchers
|
||||||
|
|
||||||
fun session(): Session
|
fun session(): Session
|
||||||
|
|
||||||
fun syncTask(): SyncTask
|
fun syncTask(): SyncTask
|
||||||
|
|
|
@ -21,6 +21,7 @@ import im.vector.matrix.android.api.failure.Failure
|
||||||
import im.vector.matrix.android.api.failure.MatrixError
|
import im.vector.matrix.android.api.failure.MatrixError
|
||||||
import im.vector.matrix.android.internal.auth.SessionParamsStore
|
import im.vector.matrix.android.internal.auth.SessionParamsStore
|
||||||
import im.vector.matrix.android.internal.di.UserId
|
import im.vector.matrix.android.internal.di.UserId
|
||||||
|
import im.vector.matrix.android.internal.network.NetworkConnectivityChecker
|
||||||
import im.vector.matrix.android.internal.network.executeRequest
|
import im.vector.matrix.android.internal.network.executeRequest
|
||||||
import im.vector.matrix.android.internal.session.DefaultInitialSyncProgressService
|
import im.vector.matrix.android.internal.session.DefaultInitialSyncProgressService
|
||||||
import im.vector.matrix.android.internal.session.filter.FilterRepository
|
import im.vector.matrix.android.internal.session.filter.FilterRepository
|
||||||
|
@ -28,6 +29,7 @@ import im.vector.matrix.android.internal.session.homeserver.GetHomeServerCapabil
|
||||||
import im.vector.matrix.android.internal.session.sync.model.SyncResponse
|
import im.vector.matrix.android.internal.session.sync.model.SyncResponse
|
||||||
import im.vector.matrix.android.internal.session.user.UserStore
|
import im.vector.matrix.android.internal.session.user.UserStore
|
||||||
import im.vector.matrix.android.internal.task.Task
|
import im.vector.matrix.android.internal.task.Task
|
||||||
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
internal interface SyncTask : Task<SyncTask.Params, Unit> {
|
internal interface SyncTask : Task<SyncTask.Params, Unit> {
|
||||||
|
@ -47,6 +49,7 @@ internal class DefaultSyncTask @Inject constructor(private val syncAPI: SyncAPI,
|
||||||
) : SyncTask {
|
) : SyncTask {
|
||||||
|
|
||||||
override suspend fun execute(params: SyncTask.Params) {
|
override suspend fun execute(params: SyncTask.Params) {
|
||||||
|
Timber.v("Sync task started on Thread: ${Thread.currentThread().name}")
|
||||||
// Maybe refresh the home server capabilities data we know
|
// Maybe refresh the home server capabilities data we know
|
||||||
getHomeServerCapabilitiesTask.execute(Unit)
|
getHomeServerCapabilitiesTask.execute(Unit)
|
||||||
|
|
||||||
|
@ -84,5 +87,6 @@ internal class DefaultSyncTask @Inject constructor(private val syncAPI: SyncAPI,
|
||||||
if (isInitialSync) {
|
if (isInitialSync) {
|
||||||
initialSyncProgressService.endAll()
|
initialSyncProgressService.endAll()
|
||||||
}
|
}
|
||||||
|
Timber.v("Sync task finished on Thread: ${Thread.currentThread().name}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,21 +18,15 @@ package im.vector.matrix.android.internal.session.sync.job
|
||||||
import android.app.Service
|
import android.app.Service
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.IBinder
|
import android.os.IBinder
|
||||||
import com.squareup.moshi.JsonEncodingException
|
|
||||||
import im.vector.matrix.android.api.Matrix
|
import im.vector.matrix.android.api.Matrix
|
||||||
import im.vector.matrix.android.api.MatrixCallback
|
import im.vector.matrix.android.api.failure.isTokenError
|
||||||
import im.vector.matrix.android.api.failure.Failure
|
|
||||||
import im.vector.matrix.android.api.failure.MatrixError
|
|
||||||
import im.vector.matrix.android.api.util.Cancelable
|
|
||||||
import im.vector.matrix.android.internal.network.NetworkConnectivityChecker
|
import im.vector.matrix.android.internal.network.NetworkConnectivityChecker
|
||||||
import im.vector.matrix.android.internal.session.sync.SyncTask
|
import im.vector.matrix.android.internal.session.sync.SyncTask
|
||||||
import im.vector.matrix.android.internal.task.TaskExecutor
|
import im.vector.matrix.android.internal.task.TaskExecutor
|
||||||
import im.vector.matrix.android.internal.task.TaskThread
|
import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
|
||||||
import im.vector.matrix.android.internal.task.configureWith
|
import kotlinx.coroutines.*
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.net.SocketTimeoutException
|
import java.util.concurrent.atomic.AtomicBoolean
|
||||||
import java.util.Timer
|
|
||||||
import java.util.TimerTask
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Can execute periodic sync task.
|
* Can execute periodic sync task.
|
||||||
|
@ -43,13 +37,15 @@ import java.util.TimerTask
|
||||||
open class SyncService : Service() {
|
open class SyncService : Service() {
|
||||||
|
|
||||||
private var mIsSelfDestroyed: Boolean = false
|
private var mIsSelfDestroyed: Boolean = false
|
||||||
private var cancelableTask: Cancelable? = null
|
|
||||||
|
|
||||||
private lateinit var syncTask: SyncTask
|
private lateinit var syncTask: SyncTask
|
||||||
private lateinit var networkConnectivityChecker: NetworkConnectivityChecker
|
private lateinit var networkConnectivityChecker: NetworkConnectivityChecker
|
||||||
private lateinit var taskExecutor: TaskExecutor
|
private lateinit var taskExecutor: TaskExecutor
|
||||||
|
private lateinit var coroutineDispatchers: MatrixCoroutineDispatchers
|
||||||
|
|
||||||
var timer = Timer()
|
private val isRunning = AtomicBoolean(false)
|
||||||
|
|
||||||
|
private val serviceScope = CoroutineScope(SupervisorJob())
|
||||||
|
|
||||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||||
Timber.i("onStartCommand $intent")
|
Timber.i("onStartCommand $intent")
|
||||||
|
@ -60,13 +56,14 @@ open class SyncService : Service() {
|
||||||
syncTask = sessionComponent.syncTask()
|
syncTask = sessionComponent.syncTask()
|
||||||
networkConnectivityChecker = sessionComponent.networkConnectivityChecker()
|
networkConnectivityChecker = sessionComponent.networkConnectivityChecker()
|
||||||
taskExecutor = sessionComponent.taskExecutor()
|
taskExecutor = sessionComponent.taskExecutor()
|
||||||
if (cancelableTask == null) {
|
coroutineDispatchers = sessionComponent.coroutineDispatchers()
|
||||||
timer.cancel()
|
if (isRunning.get()) {
|
||||||
timer = Timer()
|
Timber.i("Received a start while was already syncing... ignore")
|
||||||
doSync(true)
|
|
||||||
} else {
|
} else {
|
||||||
// Already syncing ignore
|
isRunning.set(true)
|
||||||
Timber.i("Received a start while was already syncking... ignore")
|
serviceScope.launch(coroutineDispatchers.sync) {
|
||||||
|
doSync()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// No intent just start the service, an alarm will should call with intent
|
// No intent just start the service, an alarm will should call with intent
|
||||||
|
@ -75,86 +72,40 @@ open class SyncService : Service() {
|
||||||
|
|
||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
Timber.i("## onDestroy() : $this")
|
Timber.i("## onDestroy() : $this")
|
||||||
|
|
||||||
if (!mIsSelfDestroyed) {
|
if (!mIsSelfDestroyed) {
|
||||||
Timber.w("## Destroy by the system : $this")
|
Timber.w("## Destroy by the system : $this")
|
||||||
}
|
}
|
||||||
|
serviceScope.coroutineContext.cancelChildren()
|
||||||
cancelableTask?.cancel()
|
isRunning.set(false)
|
||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun stopMe() {
|
private fun stopMe() {
|
||||||
timer.cancel()
|
|
||||||
timer = Timer()
|
|
||||||
cancelableTask?.cancel()
|
|
||||||
mIsSelfDestroyed = true
|
mIsSelfDestroyed = true
|
||||||
stopSelf()
|
stopSelf()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun doSync(once: Boolean = false) {
|
private suspend fun doSync() {
|
||||||
if (!networkConnectivityChecker.hasInternetAccess) {
|
if (!networkConnectivityChecker.hasInternetAccess()) {
|
||||||
Timber.v("No internet access. Waiting...")
|
Timber.v("No network, try to sync again in 10s")
|
||||||
// TODO Retry in ?
|
delay(DELAY_NO_NETWORK)
|
||||||
timer.schedule(object : TimerTask() {
|
doSync()
|
||||||
override fun run() {
|
return
|
||||||
doSync()
|
}
|
||||||
}
|
Timber.v("Execute sync request with timeout 0")
|
||||||
}, NO_NETWORK_DELAY)
|
val params = SyncTask.Params(TIME_OUT)
|
||||||
} else {
|
try {
|
||||||
Timber.v("Execute sync request with timeout 0")
|
syncTask.execute(params)
|
||||||
val params = SyncTask.Params(TIME_OUT)
|
stopMe()
|
||||||
cancelableTask = syncTask
|
} catch (throwable: Throwable) {
|
||||||
.configureWith(params) {
|
Timber.e(throwable)
|
||||||
callbackThread = TaskThread.SYNC
|
if (throwable.isTokenError()) {
|
||||||
executionThread = TaskThread.SYNC
|
stopMe()
|
||||||
callback = object : MatrixCallback<Unit> {
|
} else {
|
||||||
override fun onSuccess(data: Unit) {
|
Timber.v("Retry to sync in 5s")
|
||||||
cancelableTask = null
|
delay(DELAY_FAILURE)
|
||||||
if (!once) {
|
doSync()
|
||||||
timer.schedule(object : TimerTask() {
|
}
|
||||||
override fun run() {
|
|
||||||
doSync()
|
|
||||||
}
|
|
||||||
}, NEXT_BATCH_DELAY)
|
|
||||||
} else {
|
|
||||||
// stop
|
|
||||||
stopMe()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onFailure(failure: Throwable) {
|
|
||||||
Timber.e(failure)
|
|
||||||
cancelableTask = null
|
|
||||||
if (failure is Failure.NetworkConnection
|
|
||||||
&& failure.cause is SocketTimeoutException) {
|
|
||||||
// Timeout are not critical
|
|
||||||
timer.schedule(object : TimerTask() {
|
|
||||||
override fun run() {
|
|
||||||
doSync()
|
|
||||||
}
|
|
||||||
}, 5_000L)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (failure !is Failure.NetworkConnection
|
|
||||||
|| failure.cause is JsonEncodingException) {
|
|
||||||
// Wait 10s before retrying
|
|
||||||
timer.schedule(object : TimerTask() {
|
|
||||||
override fun run() {
|
|
||||||
doSync()
|
|
||||||
}
|
|
||||||
}, 5_000L)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (failure is Failure.ServerError
|
|
||||||
&& (failure.error.code == MatrixError.UNKNOWN_TOKEN || failure.error.code == MatrixError.MISSING_TOKEN)) {
|
|
||||||
// No token or invalid token, stop the thread
|
|
||||||
stopSelf()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.executeBy(taskExecutor)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,9 +115,8 @@ open class SyncService : Service() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val EXTRA_USER_ID = "EXTRA_USER_ID"
|
const val EXTRA_USER_ID = "EXTRA_USER_ID"
|
||||||
|
private const val TIME_OUT = 0L
|
||||||
const val TIME_OUT = 0L
|
private const val DELAY_NO_NETWORK = 10_000L
|
||||||
const val NEXT_BATCH_DELAY = 60_000L
|
private const val DELAY_FAILURE = 5_000L
|
||||||
const val NO_NETWORK_DELAY = 5_000L
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,11 +99,10 @@ internal class SyncThread @Inject constructor(private val syncTask: SyncTask,
|
||||||
isStarted = true
|
isStarted = true
|
||||||
networkConnectivityChecker.register(this)
|
networkConnectivityChecker.register(this)
|
||||||
backgroundDetectionObserver.register(this)
|
backgroundDetectionObserver.register(this)
|
||||||
|
|
||||||
while (state != SyncState.KILLING) {
|
while (state != SyncState.KILLING) {
|
||||||
Timber.v("Entering loop, state: $state")
|
Timber.v("Entering loop, state: $state")
|
||||||
|
|
||||||
if (!networkConnectivityChecker.hasInternetAccess) {
|
if (!networkConnectivityChecker.hasInternetAccess()) {
|
||||||
Timber.v("No network. Waiting...")
|
Timber.v("No network. Waiting...")
|
||||||
updateStateTo(SyncState.NO_NETWORK)
|
updateStateTo(SyncState.NO_NETWORK)
|
||||||
synchronized(lock) { lock.wait() }
|
synchronized(lock) { lock.wait() }
|
||||||
|
|
|
@ -18,6 +18,10 @@ package im.vector.matrix.android.internal.session.sync.job
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import androidx.work.*
|
import androidx.work.*
|
||||||
import com.squareup.moshi.JsonClass
|
import com.squareup.moshi.JsonClass
|
||||||
|
import im.vector.matrix.android.api.failure.Failure
|
||||||
|
import im.vector.matrix.android.api.failure.MatrixError
|
||||||
|
import im.vector.matrix.android.api.failure.isTokenError
|
||||||
|
import im.vector.matrix.android.internal.network.NetworkConnectivityChecker
|
||||||
import im.vector.matrix.android.internal.session.sync.SyncTask
|
import im.vector.matrix.android.internal.session.sync.SyncTask
|
||||||
import im.vector.matrix.android.internal.task.TaskExecutor
|
import im.vector.matrix.android.internal.task.TaskExecutor
|
||||||
import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
|
import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
|
||||||
|
@ -25,6 +29,7 @@ import im.vector.matrix.android.internal.worker.WorkManagerUtil
|
||||||
import im.vector.matrix.android.internal.worker.WorkManagerUtil.matrixOneTimeWorkRequestBuilder
|
import im.vector.matrix.android.internal.worker.WorkManagerUtil.matrixOneTimeWorkRequestBuilder
|
||||||
import im.vector.matrix.android.internal.worker.WorkerParamsFactory
|
import im.vector.matrix.android.internal.worker.WorkerParamsFactory
|
||||||
import im.vector.matrix.android.internal.worker.getSessionComponent
|
import im.vector.matrix.android.internal.worker.getSessionComponent
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
@ -46,45 +51,58 @@ internal class SyncWorker(context: Context,
|
||||||
@Inject lateinit var syncTask: SyncTask
|
@Inject lateinit var syncTask: SyncTask
|
||||||
@Inject lateinit var taskExecutor: TaskExecutor
|
@Inject lateinit var taskExecutor: TaskExecutor
|
||||||
@Inject lateinit var coroutineDispatchers: MatrixCoroutineDispatchers
|
@Inject lateinit var coroutineDispatchers: MatrixCoroutineDispatchers
|
||||||
|
@Inject lateinit var networkConnectivityChecker: NetworkConnectivityChecker
|
||||||
|
|
||||||
override suspend fun doWork(): Result {
|
override suspend fun doWork(): Result {
|
||||||
Timber.i("Sync work starting")
|
Timber.i("Sync work starting")
|
||||||
val params = WorkerParamsFactory.fromData<Params>(inputData) ?: return Result.success()
|
val params = WorkerParamsFactory.fromData<Params>(inputData) ?: return Result.success()
|
||||||
val sessionComponent = getSessionComponent(params.userId) ?: return Result.success()
|
val sessionComponent = getSessionComponent(params.userId) ?: return Result.success()
|
||||||
sessionComponent.inject(this)
|
sessionComponent.inject(this)
|
||||||
runCatching {
|
return runCatching {
|
||||||
withContext(coroutineDispatchers.sync) {
|
doSync(params.timeout)
|
||||||
val taskParams = SyncTask.Params(0)
|
}.fold(
|
||||||
syncTask.execute(taskParams)
|
{ Result.success() },
|
||||||
}
|
{ failure ->
|
||||||
}
|
if (failure.isTokenError() || !params.automaticallyRetry) {
|
||||||
return Result.success()
|
Result.failure()
|
||||||
|
} else {
|
||||||
|
Result.retry()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun doSync(timeout: Long) = withContext(coroutineDispatchers.sync) {
|
||||||
|
val taskParams = SyncTask.Params(timeout)
|
||||||
|
syncTask.execute(taskParams)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
|
const val BG_SYNC_WORK_NAME = "BG_SYNCP"
|
||||||
|
|
||||||
fun requireBackgroundSync(context: Context, userId: String, serverTimeout: Long = 0) {
|
fun requireBackgroundSync(context: Context, userId: String, serverTimeout: Long = 0) {
|
||||||
val data = WorkerParamsFactory.toData(Params(userId, serverTimeout, false))
|
val data = WorkerParamsFactory.toData(Params(userId, serverTimeout, false))
|
||||||
val workRequest = matrixOneTimeWorkRequestBuilder<SyncWorker>()
|
val workRequest = matrixOneTimeWorkRequestBuilder<SyncWorker>()
|
||||||
.setInputData(data)
|
|
||||||
.setConstraints(WorkManagerUtil.workConstraints)
|
.setConstraints(WorkManagerUtil.workConstraints)
|
||||||
.setBackoffCriteria(BackoffPolicy.LINEAR, 1_000, TimeUnit.MILLISECONDS)
|
.setBackoffCriteria(BackoffPolicy.LINEAR, 1_000, TimeUnit.MILLISECONDS)
|
||||||
|
.setInputData(data)
|
||||||
.build()
|
.build()
|
||||||
WorkManager.getInstance(context).enqueueUniqueWork("BG_SYNCP", ExistingWorkPolicy.REPLACE, workRequest)
|
WorkManager.getInstance(context).enqueueUniqueWork(BG_SYNC_WORK_NAME, ExistingWorkPolicy.REPLACE, workRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun automaticallyBackgroundSync(context: Context, userId: String, serverTimeout: Long = 0, delay: Long = 30_000) {
|
fun automaticallyBackgroundSync(context: Context, userId: String, serverTimeout: Long = 0, delay: Long = 30_000) {
|
||||||
val data = WorkerParamsFactory.toData(Params(userId, serverTimeout, true))
|
val data = WorkerParamsFactory.toData(Params(userId, serverTimeout, true))
|
||||||
val workRequest = matrixOneTimeWorkRequestBuilder<SyncWorker>()
|
val workRequest = matrixOneTimeWorkRequestBuilder<SyncWorker>()
|
||||||
.setInputData(data)
|
|
||||||
.setConstraints(WorkManagerUtil.workConstraints)
|
.setConstraints(WorkManagerUtil.workConstraints)
|
||||||
|
.setInputData(data)
|
||||||
.setBackoffCriteria(BackoffPolicy.LINEAR, delay, TimeUnit.MILLISECONDS)
|
.setBackoffCriteria(BackoffPolicy.LINEAR, delay, TimeUnit.MILLISECONDS)
|
||||||
.build()
|
.build()
|
||||||
WorkManager.getInstance(context).enqueueUniqueWork("BG_SYNCP", ExistingWorkPolicy.REPLACE, workRequest)
|
WorkManager.getInstance(context).enqueueUniqueWork(BG_SYNC_WORK_NAME, ExistingWorkPolicy.REPLACE, workRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun stopAnyBackgroundSync(context: Context) {
|
fun stopAnyBackgroundSync(context: Context) {
|
||||||
WorkManager.getInstance(context).cancelUniqueWork("BG_SYNCP")
|
WorkManager.getInstance(context).cancelUniqueWork(BG_SYNC_WORK_NAME)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,10 +20,6 @@
|
||||||
android:enabled="true"
|
android:enabled="true"
|
||||||
android:exported="false" />
|
android:exported="false" />
|
||||||
|
|
||||||
<service
|
|
||||||
android:name=".fdroid.service.VectorSyncService"
|
|
||||||
android:exported="false" />
|
|
||||||
|
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
|
@ -25,7 +25,7 @@ import android.os.Build
|
||||||
import android.os.PowerManager
|
import android.os.PowerManager
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import im.vector.matrix.android.internal.session.sync.job.SyncService
|
import im.vector.matrix.android.internal.session.sync.job.SyncService
|
||||||
import im.vector.riotx.fdroid.service.VectorSyncService
|
import im.vector.riotx.core.services.VectorSyncService
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
|
||||||
class AlarmSyncBroadcastReceiver : BroadcastReceiver() {
|
class AlarmSyncBroadcastReceiver : BroadcastReceiver() {
|
||||||
|
@ -41,14 +41,9 @@ class AlarmSyncBroadcastReceiver : BroadcastReceiver() {
|
||||||
val userId = intent.getStringExtra(SyncService.EXTRA_USER_ID)
|
val userId = intent.getStringExtra(SyncService.EXTRA_USER_ID)
|
||||||
// This method is called when the BroadcastReceiver is receiving an Intent broadcast.
|
// This method is called when the BroadcastReceiver is receiving an Intent broadcast.
|
||||||
Timber.d("RestartBroadcastReceiver received intent")
|
Timber.d("RestartBroadcastReceiver received intent")
|
||||||
Intent(context, VectorSyncService::class.java).also {
|
VectorSyncService.newIntent(context, userId).also {
|
||||||
it.putExtra(SyncService.EXTRA_USER_ID, userId)
|
|
||||||
try {
|
try {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
ContextCompat.startForegroundService(context, it)
|
||||||
ContextCompat.startForegroundService(context, it)
|
|
||||||
} else {
|
|
||||||
context.startService(it)
|
|
||||||
}
|
|
||||||
} catch (ex: Throwable) {
|
} catch (ex: Throwable) {
|
||||||
// TODO
|
// TODO
|
||||||
Timber.e(ex)
|
Timber.e(ex)
|
||||||
|
@ -79,6 +74,7 @@ class AlarmSyncBroadcastReceiver : BroadcastReceiver() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun cancelAlarm(context: Context) {
|
fun cancelAlarm(context: Context) {
|
||||||
|
Timber.v("Cancel alarm")
|
||||||
val intent = Intent(context, AlarmSyncBroadcastReceiver::class.java)
|
val intent = Intent(context, AlarmSyncBroadcastReceiver::class.java)
|
||||||
val pIntent = PendingIntent.getBroadcast(context, REQUEST_CODE, intent, PendingIntent.FLAG_UPDATE_CURRENT)
|
val pIntent = PendingIntent.getBroadcast(context, REQUEST_CODE, intent, PendingIntent.FLAG_UPDATE_CURRENT)
|
||||||
val alarmMgr = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
|
val alarmMgr = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
|
||||||
|
|
|
@ -104,6 +104,10 @@
|
||||||
android:name=".core.services.CallService"
|
android:name=".core.services.CallService"
|
||||||
android:exported="false" />
|
android:exported="false" />
|
||||||
|
|
||||||
|
<service
|
||||||
|
android:name=".core.services.VectorSyncService"
|
||||||
|
android:exported="false" />
|
||||||
|
|
||||||
<!-- Receivers -->
|
<!-- Receivers -->
|
||||||
|
|
||||||
<!-- Exported false, should only be accessible from this app!! -->
|
<!-- Exported false, should only be accessible from this app!! -->
|
||||||
|
|
|
@ -116,11 +116,12 @@ class VectorApplication : Application(), HasVectorInjector, MatrixConfiguration.
|
||||||
if (authenticationService.hasAuthenticatedSessions() && !activeSessionHolder.hasActiveSession()) {
|
if (authenticationService.hasAuthenticatedSessions() && !activeSessionHolder.hasActiveSession()) {
|
||||||
val lastAuthenticatedSession = authenticationService.getLastAuthenticatedSession()!!
|
val lastAuthenticatedSession = authenticationService.getLastAuthenticatedSession()!!
|
||||||
activeSessionHolder.setActiveSession(lastAuthenticatedSession)
|
activeSessionHolder.setActiveSession(lastAuthenticatedSession)
|
||||||
lastAuthenticatedSession.configureAndStart(pushRuleTriggerListener, sessionListener)
|
lastAuthenticatedSession.configureAndStart(applicationContext, pushRuleTriggerListener, sessionListener)
|
||||||
}
|
}
|
||||||
ProcessLifecycleOwner.get().lifecycle.addObserver(object : LifecycleObserver {
|
ProcessLifecycleOwner.get().lifecycle.addObserver(object : LifecycleObserver {
|
||||||
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
|
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
|
||||||
fun entersForeground() {
|
fun entersForeground() {
|
||||||
|
Timber.i("App entered foreground")
|
||||||
FcmHelper.onEnterForeground(appContext)
|
FcmHelper.onEnterForeground(appContext)
|
||||||
activeSessionHolder.getSafeActiveSession()?.also {
|
activeSessionHolder.getSafeActiveSession()?.also {
|
||||||
it.stopAnyBackgroundSync()
|
it.stopAnyBackgroundSync()
|
||||||
|
|
|
@ -16,23 +16,27 @@
|
||||||
|
|
||||||
package im.vector.riotx.core.extensions
|
package im.vector.riotx.core.extensions
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.lifecycle.Lifecycle
|
import androidx.lifecycle.Lifecycle
|
||||||
import androidx.lifecycle.ProcessLifecycleOwner
|
import androidx.lifecycle.ProcessLifecycleOwner
|
||||||
import im.vector.matrix.android.api.session.Session
|
import im.vector.matrix.android.api.session.Session
|
||||||
import im.vector.matrix.android.api.session.sync.FilterService
|
import im.vector.matrix.android.api.session.sync.FilterService
|
||||||
|
import im.vector.matrix.android.internal.session.sync.job.SyncService
|
||||||
|
import im.vector.riotx.core.services.VectorSyncService
|
||||||
import im.vector.riotx.features.notifications.PushRuleTriggerListener
|
import im.vector.riotx.features.notifications.PushRuleTriggerListener
|
||||||
import im.vector.riotx.features.session.SessionListener
|
import im.vector.riotx.features.session.SessionListener
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
|
||||||
fun Session.configureAndStart(pushRuleTriggerListener: PushRuleTriggerListener,
|
fun Session.configureAndStart(context: Context,
|
||||||
|
pushRuleTriggerListener: PushRuleTriggerListener,
|
||||||
sessionListener: SessionListener) {
|
sessionListener: SessionListener) {
|
||||||
open()
|
open()
|
||||||
addListener(sessionListener)
|
addListener(sessionListener)
|
||||||
setFilter(FilterService.FilterPreset.RiotFilter)
|
setFilter(FilterService.FilterPreset.RiotFilter)
|
||||||
Timber.i("Configure and start session for ${this.myUserId}")
|
Timber.i("Configure and start session for ${this.myUserId}")
|
||||||
val isAtLeastStarted = ProcessLifecycleOwner.get().lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)
|
startSyncing(context)
|
||||||
Timber.v("--> is at least started? $isAtLeastStarted")
|
|
||||||
startSync(isAtLeastStarted)
|
|
||||||
refreshPushers()
|
refreshPushers()
|
||||||
pushRuleTriggerListener.startWithSession(this)
|
pushRuleTriggerListener.startWithSession(this)
|
||||||
|
|
||||||
|
@ -40,3 +44,20 @@ fun Session.configureAndStart(pushRuleTriggerListener: PushRuleTriggerListener,
|
||||||
// @Inject lateinit var incomingVerificationRequestHandler: IncomingVerificationRequestHandler
|
// @Inject lateinit var incomingVerificationRequestHandler: IncomingVerificationRequestHandler
|
||||||
// @Inject lateinit var keyRequestHandler: KeyRequestHandler
|
// @Inject lateinit var keyRequestHandler: KeyRequestHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun Session.startSyncing(context: Context) {
|
||||||
|
val applicationContext = context.applicationContext
|
||||||
|
if (!hasAlreadySynced()) {
|
||||||
|
VectorSyncService.newIntent(applicationContext, myUserId).also {
|
||||||
|
try {
|
||||||
|
ContextCompat.startForegroundService(applicationContext, it)
|
||||||
|
} catch (ex: Throwable) {
|
||||||
|
// TODO
|
||||||
|
Timber.e(ex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val isAtLeastStarted = ProcessLifecycleOwner.get().lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)
|
||||||
|
Timber.v("--> is at least started? $isAtLeastStarted")
|
||||||
|
startSync(isAtLeastStarted)
|
||||||
|
}
|
||||||
|
|
|
@ -13,12 +13,13 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package im.vector.riotx.fdroid.service
|
package im.vector.riotx.core.services
|
||||||
|
|
||||||
import android.app.NotificationManager
|
import android.app.NotificationManager
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
import im.vector.matrix.android.internal.session.sync.job.SyncService
|
import im.vector.matrix.android.internal.session.sync.job.SyncService
|
||||||
import im.vector.riotx.R
|
import im.vector.riotx.R
|
||||||
import im.vector.riotx.core.extensions.vectorComponent
|
import im.vector.riotx.core.extensions.vectorComponent
|
||||||
|
@ -27,6 +28,15 @@ import timber.log.Timber
|
||||||
|
|
||||||
class VectorSyncService : SyncService() {
|
class VectorSyncService : SyncService() {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
fun newIntent(context: Context, userId: String): Intent {
|
||||||
|
return Intent(context, VectorSyncService::class.java).also {
|
||||||
|
it.putExtra(EXTRA_USER_ID, userId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private lateinit var notificationUtils: NotificationUtils
|
private lateinit var notificationUtils: NotificationUtils
|
||||||
|
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
|
@ -45,8 +55,7 @@ class VectorSyncService : SyncService() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service is started only in fdroid mode when no FCM is available
|
* Service is started in fdroid mode when no FCM is available or is used for initialSync
|
||||||
* Otherwise it is bounded
|
|
||||||
*/
|
*/
|
||||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||||
Timber.v("VectorSyncService - onStartCommand ")
|
Timber.v("VectorSyncService - onStartCommand ")
|
|
@ -26,6 +26,8 @@ import im.vector.riotx.R
|
||||||
import im.vector.riotx.core.di.ActiveSessionHolder
|
import im.vector.riotx.core.di.ActiveSessionHolder
|
||||||
import im.vector.riotx.core.di.ScreenComponent
|
import im.vector.riotx.core.di.ScreenComponent
|
||||||
import im.vector.riotx.core.error.ErrorFormatter
|
import im.vector.riotx.core.error.ErrorFormatter
|
||||||
|
import im.vector.riotx.core.extensions.configureAndStart
|
||||||
|
import im.vector.riotx.core.extensions.startSyncing
|
||||||
import im.vector.riotx.core.platform.VectorBaseActivity
|
import im.vector.riotx.core.platform.VectorBaseActivity
|
||||||
import im.vector.riotx.core.utils.deleteAllFiles
|
import im.vector.riotx.core.utils.deleteAllFiles
|
||||||
import im.vector.riotx.features.home.HomeActivity
|
import im.vector.riotx.features.home.HomeActivity
|
||||||
|
@ -75,8 +77,13 @@ class MainActivity : VectorBaseActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun doCleanUp(clearCache: Boolean, clearCredentials: Boolean) {
|
private fun doCleanUp(clearCache: Boolean, clearCredentials: Boolean) {
|
||||||
|
val session = sessionHolder.getSafeActiveSession()
|
||||||
|
if (session == null) {
|
||||||
|
start()
|
||||||
|
return
|
||||||
|
}
|
||||||
when {
|
when {
|
||||||
clearCredentials -> sessionHolder.getActiveSession().signOut(object : MatrixCallback<Unit> {
|
clearCredentials -> session.signOut(object : MatrixCallback<Unit> {
|
||||||
override fun onSuccess(data: Unit) {
|
override fun onSuccess(data: Unit) {
|
||||||
Timber.w("SIGN_OUT: success, start app")
|
Timber.w("SIGN_OUT: success, start app")
|
||||||
sessionHolder.clearActiveSession()
|
sessionHolder.clearActiveSession()
|
||||||
|
@ -87,8 +94,9 @@ class MainActivity : VectorBaseActivity() {
|
||||||
displayError(failure, clearCache, clearCredentials)
|
displayError(failure, clearCache, clearCredentials)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
clearCache -> sessionHolder.getActiveSession().clearCache(object : MatrixCallback<Unit> {
|
clearCache -> session.clearCache(object : MatrixCallback<Unit> {
|
||||||
override fun onSuccess(data: Unit) {
|
override fun onSuccess(data: Unit) {
|
||||||
|
session.startSyncing(applicationContext)
|
||||||
doLocalCleanupAndStart()
|
doLocalCleanupAndStart()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
package im.vector.riotx.features.login
|
package im.vector.riotx.features.login
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
import com.airbnb.mvrx.*
|
import com.airbnb.mvrx.*
|
||||||
import com.squareup.inject.assisted.Assisted
|
import com.squareup.inject.assisted.Assisted
|
||||||
import com.squareup.inject.assisted.AssistedInject
|
import com.squareup.inject.assisted.AssistedInject
|
||||||
|
@ -44,6 +45,7 @@ import java.util.concurrent.CancellationException
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
class LoginViewModel @AssistedInject constructor(@Assisted initialState: LoginViewState,
|
class LoginViewModel @AssistedInject constructor(@Assisted initialState: LoginViewState,
|
||||||
|
private val applicationContext: Context,
|
||||||
private val authenticationService: AuthenticationService,
|
private val authenticationService: AuthenticationService,
|
||||||
private val activeSessionHolder: ActiveSessionHolder,
|
private val activeSessionHolder: ActiveSessionHolder,
|
||||||
private val pushRuleTriggerListener: PushRuleTriggerListener,
|
private val pushRuleTriggerListener: PushRuleTriggerListener,
|
||||||
|
@ -469,7 +471,7 @@ class LoginViewModel @AssistedInject constructor(@Assisted initialState: LoginVi
|
||||||
|
|
||||||
private fun onSessionCreated(session: Session) {
|
private fun onSessionCreated(session: Session) {
|
||||||
activeSessionHolder.setActiveSession(session)
|
activeSessionHolder.setActiveSession(session)
|
||||||
session.configureAndStart(pushRuleTriggerListener, sessionListener)
|
session.configureAndStart(applicationContext, pushRuleTriggerListener, sessionListener)
|
||||||
setState {
|
setState {
|
||||||
copy(
|
copy(
|
||||||
asyncLoginAction = Success(Unit)
|
asyncLoginAction = Success(Unit)
|
||||||
|
|
Loading…
Reference in a new issue