diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/network/NetworkConnectivityChecker.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/network/NetworkConnectivityChecker.kt index 4d4699810f..e6dda3f5e1 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/network/NetworkConnectivityChecker.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/network/NetworkConnectivityChecker.kt @@ -62,6 +62,9 @@ internal class NetworkConnectivityChecker @Inject constructor(private val contex override fun onMoveToForeground() { merlin.bind() + merlinsBeard.hasInternetAccess { + hasInternetAccess = it + } merlin.registerDisconnectable { if (hasInternetAccess) { Timber.v("On Disconnect") diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/job/SyncService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/job/SyncService.kt index 3aeb408db1..8a91186e07 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/job/SyncService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/job/SyncService.kt @@ -34,8 +34,9 @@ import java.util.concurrent.atomic.AtomicBoolean * in order to be able to perform a sync even if the app is not running. * The and must be declared in the Manifest or the app using the SDK */ -open class SyncService : Service() { +abstract class SyncService : Service() { + private var userId: String? = null private var mIsSelfDestroyed: Boolean = false private lateinit var syncTask: SyncTask @@ -50,9 +51,10 @@ open class SyncService : Service() { override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { Timber.i("onStartCommand $intent") intent?.let { - val userId = it.getStringExtra(EXTRA_USER_ID) - val sessionComponent = Matrix.getInstance(applicationContext).sessionManager.getSessionComponent(userId) + val safeUserId = it.getStringExtra(EXTRA_USER_ID) ?: return@let + val sessionComponent = Matrix.getInstance(applicationContext).sessionManager.getSessionComponent(safeUserId) ?: return@let + userId = safeUserId syncTask = sessionComponent.syncTask() networkConnectivityChecker = sessionComponent.networkConnectivityChecker() taskExecutor = sessionComponent.taskExecutor() @@ -87,9 +89,11 @@ open class SyncService : Service() { private suspend fun doSync() { if (!networkConnectivityChecker.hasInternetAccess()) { - Timber.v("No network, try to sync again in 10s") - delay(DELAY_NO_NETWORK) - doSync() + Timber.v("No network reschedule to avoid wasting resources") + userId?.also { + onRescheduleAsked(it, delay = 10_000L) + } + stopMe() return } Timber.v("Execute sync request with timeout 0") @@ -109,6 +113,8 @@ open class SyncService : Service() { } } + abstract fun onRescheduleAsked(userId: String, delay: Long) + override fun onBind(intent: Intent?): IBinder? { return null } @@ -116,7 +122,6 @@ open class SyncService : Service() { companion object { const val EXTRA_USER_ID = "EXTRA_USER_ID" private const val TIME_OUT = 0L - private const val DELAY_NO_NETWORK = 10_000L private const val DELAY_FAILURE = 5_000L } } diff --git a/vector/src/gplay/AndroidManifest.xml b/vector/src/gplay/AndroidManifest.xml index db30f21f7a..85567df2c1 100755 --- a/vector/src/gplay/AndroidManifest.xml +++ b/vector/src/gplay/AndroidManifest.xml @@ -2,6 +2,8 @@ + + diff --git a/vector/src/main/java/im/vector/riotx/core/services/VectorSyncService.kt b/vector/src/main/java/im/vector/riotx/core/services/VectorSyncService.kt index 175f921e07..93c08c50d6 100644 --- a/vector/src/main/java/im/vector/riotx/core/services/VectorSyncService.kt +++ b/vector/src/main/java/im/vector/riotx/core/services/VectorSyncService.kt @@ -15,11 +15,12 @@ */ package im.vector.riotx.core.services +import android.app.AlarmManager import android.app.NotificationManager +import android.app.PendingIntent import android.content.Context import android.content.Intent import android.os.Build -import androidx.core.content.ContextCompat import im.vector.matrix.android.internal.session.sync.job.SyncService import im.vector.riotx.R import im.vector.riotx.core.extensions.vectorComponent @@ -44,16 +45,6 @@ class VectorSyncService : SyncService() { notificationUtils = vectorComponent().notificationUtils() } - override fun onDestroy() { - removeForegroundNotif() - super.onDestroy() - } - - private fun removeForegroundNotif() { - val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager - notificationManager.cancel(NotificationUtils.NOTIFICATION_ID_FOREGROUND_SERVICE) - } - /** * Service is started in fdroid mode when no FCM is available or is used for initialSync */ @@ -65,4 +56,33 @@ class VectorSyncService : SyncService() { } return super.onStartCommand(intent, flags, startId) } + + override fun onDestroy() { + removeForegroundNotif() + super.onDestroy() + } + + override fun onRescheduleAsked(userId: String, delay: Long) { + reschedule(userId, delay) + } + + private fun removeForegroundNotif() { + val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager + notificationManager.cancel(NotificationUtils.NOTIFICATION_ID_FOREGROUND_SERVICE) + } + + private fun reschedule(userId: String, delay: Long) { + val pendingIntent = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + PendingIntent.getForegroundService(this, 0, newIntent(this, userId), 0) + } else { + PendingIntent.getService(this, 0, newIntent(this, userId), 0) + } + val firstMillis = System.currentTimeMillis() + delay + val alarmMgr = getSystemService(Context.ALARM_SERVICE) as AlarmManager + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + alarmMgr.setAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, firstMillis, pendingIntent) + } else { + alarmMgr.set(AlarmManager.RTC_WAKEUP, firstMillis, pendingIntent) + } + } }