Sync: fix crash on gplay flavor and reschedule when no network instead of showing a potential notification all the time

This commit is contained in:
ganfra 2019-12-11 16:24:30 +01:00
parent 5338f93852
commit 3a269be2ef
4 changed files with 48 additions and 18 deletions

View File

@ -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")

View File

@ -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 <receiver> and <service> 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
}
}

View File

@ -2,6 +2,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="im.vector.riotx">
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<application>
<!-- Firebase components -->

View File

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