mirror of
https://github.com/etesync/android
synced 2024-11-26 01:48:34 +00:00
Unify all of the sync adapter exception handling.
The exception handling was duplicated across every sync backend. It was redundant and made it easy to not handle all of the exceptions correctly everywhere.
This commit is contained in:
parent
6250cacd30
commit
2615fbd9ce
@ -40,14 +40,10 @@ class AddressBooksSyncAdapterService : SyncAdapterService() {
|
|||||||
|
|
||||||
|
|
||||||
private class AddressBooksSyncAdapter(context: Context) : SyncAdapterService.SyncAdapter(context) {
|
private class AddressBooksSyncAdapter(context: Context) : SyncAdapterService.SyncAdapter(context) {
|
||||||
|
override val syncErrorTitle = R.string.sync_error_contacts
|
||||||
|
override val notificationManager = SyncNotification(context, "journals-contacts", Constants.NOTIFICATION_CONTACTS_SYNC)
|
||||||
|
|
||||||
override fun onPerformSync(account: Account, extras: Bundle, authority: String, provider: ContentProviderClient, syncResult: SyncResult) {
|
override fun onPerformSyncDo(account: Account, extras: Bundle, authority: String, provider: ContentProviderClient, syncResult: SyncResult) {
|
||||||
super.onPerformSync(account, extras, authority, provider, syncResult)
|
|
||||||
|
|
||||||
val notificationManager = SyncNotification(context, "journals-contacts", Constants.NOTIFICATION_CONTACTS_SYNC)
|
|
||||||
notificationManager.cancel()
|
|
||||||
|
|
||||||
try {
|
|
||||||
val contactsProvider = context.contentResolver.acquireContentProviderClient(ContactsContract.AUTHORITY)
|
val contactsProvider = context.contentResolver.acquireContentProviderClient(ContactsContract.AUTHORITY)
|
||||||
if (contactsProvider == null) {
|
if (contactsProvider == null) {
|
||||||
Logger.log.severe("Couldn't access contacts provider")
|
Logger.log.severe("Couldn't access contacts provider")
|
||||||
@ -73,38 +69,6 @@ class AddressBooksSyncAdapterService : SyncAdapterService() {
|
|||||||
syncExtras.putBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_BACKOFF, true)
|
syncExtras.putBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_BACKOFF, true)
|
||||||
ContentResolver.requestSync(addressBookAccount, ContactsContract.AUTHORITY, syncExtras)
|
ContentResolver.requestSync(addressBookAccount, ContactsContract.AUTHORITY, syncExtras)
|
||||||
}
|
}
|
||||||
} catch (e: Exceptions.ServiceUnavailableException) {
|
|
||||||
syncResult.stats.numIoExceptions++
|
|
||||||
syncResult.delayUntil = if (e.retryAfter > 0) e.retryAfter else Constants.DEFAULT_RETRY_DELAY
|
|
||||||
} catch (e: Exceptions.IgnorableHttpException) {
|
|
||||||
// Ignore
|
|
||||||
} catch (e: Exception) {
|
|
||||||
if (e is ContactsStorageException || e is SQLiteException) {
|
|
||||||
Logger.log.log(Level.SEVERE, "Couldn't prepare local address books", e)
|
|
||||||
syncResult.databaseError = true
|
|
||||||
}
|
|
||||||
|
|
||||||
val syncPhase = R.string.sync_phase_journals
|
|
||||||
val title = context.getString(R.string.sync_error_contacts, account.name)
|
|
||||||
|
|
||||||
notificationManager.setThrowable(e)
|
|
||||||
|
|
||||||
val detailsIntent = notificationManager.detailsIntent
|
|
||||||
detailsIntent.putExtra(KEY_ACCOUNT, account)
|
|
||||||
if (e !is Exceptions.UnauthorizedException) {
|
|
||||||
detailsIntent.putExtra(DebugInfoActivity.KEY_AUTHORITY, authority)
|
|
||||||
detailsIntent.putExtra(DebugInfoActivity.KEY_PHASE, syncPhase)
|
|
||||||
}
|
|
||||||
|
|
||||||
notificationManager.notify(title, context.getString(syncPhase))
|
|
||||||
} catch (e: OutOfMemoryError) {
|
|
||||||
val syncPhase = R.string.sync_phase_journals
|
|
||||||
val title = context.getString(R.string.sync_error_contacts, account.name)
|
|
||||||
notificationManager.setThrowable(e)
|
|
||||||
val detailsIntent = notificationManager.detailsIntent
|
|
||||||
detailsIntent.putExtra(KEY_ACCOUNT, account)
|
|
||||||
notificationManager.notify(title, context.getString(syncPhase))
|
|
||||||
}
|
|
||||||
|
|
||||||
Logger.log.info("Address book sync complete")
|
Logger.log.info("Address book sync complete")
|
||||||
}
|
}
|
||||||
|
@ -31,21 +31,16 @@ import java.util.*
|
|||||||
import java.util.logging.Level
|
import java.util.logging.Level
|
||||||
|
|
||||||
class CalendarsSyncAdapterService : SyncAdapterService() {
|
class CalendarsSyncAdapterService : SyncAdapterService() {
|
||||||
|
|
||||||
override fun syncAdapter(): AbstractThreadedSyncAdapter {
|
override fun syncAdapter(): AbstractThreadedSyncAdapter {
|
||||||
return SyncAdapter(this)
|
return SyncAdapter(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private class SyncAdapter(context: Context) : SyncAdapterService.SyncAdapter(context) {
|
private class SyncAdapter(context: Context) : SyncAdapterService.SyncAdapter(context) {
|
||||||
|
override val syncErrorTitle = R.string.sync_error_calendar
|
||||||
|
override val notificationManager = SyncNotification(context, "journals-calendar", Constants.NOTIFICATION_CALENDAR_SYNC)
|
||||||
|
|
||||||
override fun onPerformSync(account: Account, extras: Bundle, authority: String, provider: ContentProviderClient, syncResult: SyncResult) {
|
override fun onPerformSyncDo(account: Account, extras: Bundle, authority: String, provider: ContentProviderClient, syncResult: SyncResult) {
|
||||||
super.onPerformSync(account, extras, authority, provider, syncResult)
|
|
||||||
|
|
||||||
val notificationManager = SyncNotification(context, "journals-calendar", Constants.NOTIFICATION_CALENDAR_SYNC)
|
|
||||||
notificationManager.cancel()
|
|
||||||
|
|
||||||
try {
|
|
||||||
val settings = AccountSettings(context, account)
|
val settings = AccountSettings(context, account)
|
||||||
if (!extras.containsKey(ContentResolver.SYNC_EXTRAS_MANUAL) && !checkSyncConditions(settings))
|
if (!extras.containsKey(ContentResolver.SYNC_EXTRAS_MANUAL) && !checkSyncConditions(settings))
|
||||||
return
|
return
|
||||||
@ -62,38 +57,6 @@ class CalendarsSyncAdapterService : SyncAdapterService() {
|
|||||||
it.performSync()
|
it.performSync()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e: Exceptions.ServiceUnavailableException) {
|
|
||||||
syncResult.stats.numIoExceptions++
|
|
||||||
syncResult.delayUntil = if (e.retryAfter > 0) e.retryAfter else Constants.DEFAULT_RETRY_DELAY
|
|
||||||
} catch (e: Exceptions.IgnorableHttpException) {
|
|
||||||
// Ignore
|
|
||||||
} catch (e: Exception) {
|
|
||||||
if (e is CalendarStorageException || e is SQLiteException) {
|
|
||||||
Logger.log.log(Level.SEVERE, "Couldn't prepare local calendars", e)
|
|
||||||
syncResult.databaseError = true
|
|
||||||
}
|
|
||||||
|
|
||||||
val syncPhase = R.string.sync_phase_journals
|
|
||||||
val title = context.getString(R.string.sync_error_calendar, account.name)
|
|
||||||
|
|
||||||
notificationManager.setThrowable(e)
|
|
||||||
|
|
||||||
val detailsIntent = notificationManager.detailsIntent
|
|
||||||
detailsIntent.putExtra(KEY_ACCOUNT, account)
|
|
||||||
if (e !is Exceptions.UnauthorizedException) {
|
|
||||||
detailsIntent.putExtra(DebugInfoActivity.KEY_AUTHORITY, authority)
|
|
||||||
detailsIntent.putExtra(DebugInfoActivity.KEY_PHASE, syncPhase)
|
|
||||||
}
|
|
||||||
|
|
||||||
notificationManager.notify(title, context.getString(syncPhase))
|
|
||||||
} catch (e: OutOfMemoryError) {
|
|
||||||
val syncPhase = R.string.sync_phase_journals
|
|
||||||
val title = context.getString(R.string.sync_error_calendar, account.name)
|
|
||||||
notificationManager.setThrowable(e)
|
|
||||||
val detailsIntent = notificationManager.detailsIntent
|
|
||||||
detailsIntent.putExtra(KEY_ACCOUNT, account)
|
|
||||||
notificationManager.notify(title, context.getString(syncPhase))
|
|
||||||
}
|
|
||||||
|
|
||||||
Logger.log.info("Calendar sync complete")
|
Logger.log.info("Calendar sync complete")
|
||||||
}
|
}
|
||||||
|
@ -30,13 +30,10 @@ class ContactsSyncAdapterService : SyncAdapterService() {
|
|||||||
|
|
||||||
|
|
||||||
private class ContactsSyncAdapter(context: Context) : SyncAdapterService.SyncAdapter(context) {
|
private class ContactsSyncAdapter(context: Context) : SyncAdapterService.SyncAdapter(context) {
|
||||||
|
override val syncErrorTitle = R.string.sync_error_contacts
|
||||||
|
override val notificationManager = SyncNotification(context, "journals-contacts", Constants.NOTIFICATION_CONTACTS_SYNC)
|
||||||
|
|
||||||
override fun onPerformSync(account: Account, extras: Bundle, authority: String, provider: ContentProviderClient, syncResult: SyncResult) {
|
override fun onPerformSyncDo(account: Account, extras: Bundle, authority: String, provider: ContentProviderClient, syncResult: SyncResult) {
|
||||||
super.onPerformSync(account, extras, authority, provider, syncResult)
|
|
||||||
val notificationManager = SyncNotification(context, "journals-contacts", Constants.NOTIFICATION_CONTACTS_SYNC)
|
|
||||||
notificationManager.cancel()
|
|
||||||
|
|
||||||
try {
|
|
||||||
val addressBook = LocalAddressBook(context, account, provider)
|
val addressBook = LocalAddressBook(context, account, provider)
|
||||||
|
|
||||||
val settings: AccountSettings
|
val settings: AccountSettings
|
||||||
@ -62,32 +59,6 @@ class ContactsSyncAdapterService : SyncAdapterService() {
|
|||||||
ContactsSyncManager(context, account, settings, extras, authority, provider, syncResult, addressBook, principal).use {
|
ContactsSyncManager(context, account, settings, extras, authority, provider, syncResult, addressBook, principal).use {
|
||||||
it.performSync()
|
it.performSync()
|
||||||
}
|
}
|
||||||
} catch (e: Exceptions.ServiceUnavailableException) {
|
|
||||||
syncResult.stats.numIoExceptions++
|
|
||||||
syncResult.delayUntil = if (e.retryAfter > 0) e.retryAfter else Constants.DEFAULT_RETRY_DELAY
|
|
||||||
} catch (e: Exceptions.IgnorableHttpException) {
|
|
||||||
// Ignore
|
|
||||||
} catch (e: Exception) {
|
|
||||||
val syncPhase = R.string.sync_phase_journals
|
|
||||||
val title = context.getString(R.string.sync_error_contacts, account.name)
|
|
||||||
|
|
||||||
notificationManager.setThrowable(e)
|
|
||||||
|
|
||||||
val detailsIntent = notificationManager.detailsIntent
|
|
||||||
detailsIntent.putExtra(KEY_ACCOUNT, account)
|
|
||||||
if (e !is Exceptions.UnauthorizedException) {
|
|
||||||
detailsIntent.putExtra(DebugInfoActivity.KEY_AUTHORITY, authority)
|
|
||||||
detailsIntent.putExtra(DebugInfoActivity.KEY_PHASE, syncPhase)
|
|
||||||
}
|
|
||||||
notificationManager.notify(title, context.getString(syncPhase))
|
|
||||||
} catch (e: OutOfMemoryError) {
|
|
||||||
val syncPhase = R.string.sync_phase_journals
|
|
||||||
val title = context.getString(R.string.sync_error_contacts, account.name)
|
|
||||||
notificationManager.setThrowable(e)
|
|
||||||
val detailsIntent = notificationManager.detailsIntent
|
|
||||||
detailsIntent.putExtra(KEY_ACCOUNT, account)
|
|
||||||
notificationManager.notify(title, context.getString(syncPhase))
|
|
||||||
}
|
|
||||||
|
|
||||||
Logger.log.info("Contacts sync complete")
|
Logger.log.info("Contacts sync complete")
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ import android.accounts.Account
|
|||||||
import android.app.PendingIntent
|
import android.app.PendingIntent
|
||||||
import android.app.Service
|
import android.app.Service
|
||||||
import android.content.*
|
import android.content.*
|
||||||
|
import android.database.sqlite.SQLiteException
|
||||||
import android.net.ConnectivityManager
|
import android.net.ConnectivityManager
|
||||||
import android.net.wifi.WifiManager
|
import android.net.wifi.WifiManager
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
@ -19,6 +20,8 @@ import android.os.IBinder
|
|||||||
import androidx.core.app.NotificationCompat
|
import androidx.core.app.NotificationCompat
|
||||||
import androidx.core.app.NotificationManagerCompat
|
import androidx.core.app.NotificationManagerCompat
|
||||||
import androidx.core.util.Pair
|
import androidx.core.util.Pair
|
||||||
|
import at.bitfire.ical4android.CalendarStorageException
|
||||||
|
import at.bitfire.vcard4android.ContactsStorageException
|
||||||
import com.etesync.syncadapter.*
|
import com.etesync.syncadapter.*
|
||||||
import com.etesync.syncadapter.journalmanager.Crypto
|
import com.etesync.syncadapter.journalmanager.Crypto
|
||||||
import com.etesync.syncadapter.journalmanager.Exceptions
|
import com.etesync.syncadapter.journalmanager.Exceptions
|
||||||
@ -27,6 +30,7 @@ import com.etesync.syncadapter.log.Logger
|
|||||||
import com.etesync.syncadapter.model.CollectionInfo
|
import com.etesync.syncadapter.model.CollectionInfo
|
||||||
import com.etesync.syncadapter.model.JournalEntity
|
import com.etesync.syncadapter.model.JournalEntity
|
||||||
import com.etesync.syncadapter.model.JournalModel
|
import com.etesync.syncadapter.model.JournalModel
|
||||||
|
import com.etesync.syncadapter.ui.DebugInfoActivity
|
||||||
import com.etesync.syncadapter.ui.PermissionsActivity
|
import com.etesync.syncadapter.ui.PermissionsActivity
|
||||||
import com.etesync.syncadapter.utils.NotificationUtils
|
import com.etesync.syncadapter.utils.NotificationUtils
|
||||||
import okhttp3.HttpUrl
|
import okhttp3.HttpUrl
|
||||||
@ -45,12 +49,53 @@ abstract class SyncAdapterService : Service() {
|
|||||||
|
|
||||||
|
|
||||||
abstract class SyncAdapter(context: Context) : AbstractThreadedSyncAdapter(context, false) {
|
abstract class SyncAdapter(context: Context) : AbstractThreadedSyncAdapter(context, false) {
|
||||||
|
abstract val syncErrorTitle: Int
|
||||||
|
abstract val notificationManager: SyncNotification
|
||||||
|
|
||||||
|
abstract fun onPerformSyncDo(account: Account, extras: Bundle, authority: String, provider: ContentProviderClient, syncResult: SyncResult)
|
||||||
|
|
||||||
override fun onPerformSync(account: Account, extras: Bundle, authority: String, provider: ContentProviderClient, syncResult: SyncResult) {
|
override fun onPerformSync(account: Account, extras: Bundle, authority: String, provider: ContentProviderClient, syncResult: SyncResult) {
|
||||||
Logger.log.log(Level.INFO, "$authority sync of $account has been initiated.", extras.keySet().toTypedArray())
|
Logger.log.log(Level.INFO, "$authority sync of $account has been initiated.", extras.keySet().toTypedArray())
|
||||||
|
|
||||||
// required for dav4android (ServiceLoader)
|
// required for dav4android (ServiceLoader)
|
||||||
Thread.currentThread().contextClassLoader = context.classLoader
|
Thread.currentThread().contextClassLoader = context.classLoader
|
||||||
|
|
||||||
|
notificationManager.cancel()
|
||||||
|
|
||||||
|
try {
|
||||||
|
onPerformSyncDo(account, extras, authority, provider, syncResult)
|
||||||
|
} catch (e: Exceptions.ServiceUnavailableException) {
|
||||||
|
syncResult.stats.numIoExceptions++
|
||||||
|
syncResult.delayUntil = if (e.retryAfter > 0) e.retryAfter else Constants.DEFAULT_RETRY_DELAY
|
||||||
|
} catch (e: Exceptions.IgnorableHttpException) {
|
||||||
|
// Ignore
|
||||||
|
} catch (e: Exception) {
|
||||||
|
if (e is ContactsStorageException || e is CalendarStorageException || e is SQLiteException) {
|
||||||
|
Logger.log.log(Level.SEVERE, "Couldn't prepare local journals", e)
|
||||||
|
syncResult.databaseError = true
|
||||||
|
}
|
||||||
|
|
||||||
|
val syncPhase = R.string.sync_phase_journals
|
||||||
|
val title = context.getString(syncErrorTitle, account.name)
|
||||||
|
|
||||||
|
notificationManager.setThrowable(e)
|
||||||
|
|
||||||
|
val detailsIntent = notificationManager.detailsIntent
|
||||||
|
detailsIntent.putExtra(Constants.KEY_ACCOUNT, account)
|
||||||
|
if (e !is Exceptions.UnauthorizedException) {
|
||||||
|
detailsIntent.putExtra(DebugInfoActivity.KEY_AUTHORITY, authority)
|
||||||
|
detailsIntent.putExtra(DebugInfoActivity.KEY_PHASE, syncPhase)
|
||||||
|
}
|
||||||
|
|
||||||
|
notificationManager.notify(title, context.getString(syncPhase))
|
||||||
|
} catch (e: OutOfMemoryError) {
|
||||||
|
val syncPhase = R.string.sync_phase_journals
|
||||||
|
val title = context.getString(syncErrorTitle, account.name)
|
||||||
|
notificationManager.setThrowable(e)
|
||||||
|
val detailsIntent = notificationManager.detailsIntent
|
||||||
|
detailsIntent.putExtra(Constants.KEY_ACCOUNT, account)
|
||||||
|
notificationManager.notify(title, context.getString(syncPhase))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSecurityException(account: Account, extras: Bundle, authority: String, syncResult: SyncResult) {
|
override fun onSecurityException(account: Account, extras: Bundle, authority: String, syncResult: SyncResult) {
|
||||||
|
@ -45,14 +45,11 @@ class TasksSyncAdapterService: SyncAdapterService() {
|
|||||||
class TasksSyncAdapter(
|
class TasksSyncAdapter(
|
||||||
context: Context
|
context: Context
|
||||||
): SyncAdapter(context) {
|
): SyncAdapter(context) {
|
||||||
|
override val syncErrorTitle = R.string.sync_error_tasks
|
||||||
|
override val notificationManager = SyncNotification(context, "journals-tasks", Constants.NOTIFICATION_TASK_SYNC)
|
||||||
|
|
||||||
override fun onPerformSync(account: Account, extras: Bundle, authority: String, provider: ContentProviderClient, syncResult: SyncResult) {
|
override fun onPerformSyncDo(account: Account, extras: Bundle, authority: String, provider: ContentProviderClient, syncResult: SyncResult) {
|
||||||
super.onPerformSync(account, extras, authority, provider, syncResult)
|
|
||||||
|
|
||||||
val notificationManager = SyncNotification(context, "journals-tasks", Constants.NOTIFICATION_TASK_SYNC)
|
|
||||||
notificationManager.cancel()
|
|
||||||
|
|
||||||
try {
|
|
||||||
val taskProvider = TaskProvider.fromProviderClient(context, provider)
|
val taskProvider = TaskProvider.fromProviderClient(context, provider)
|
||||||
|
|
||||||
// make sure account can be seen by OpenTasks
|
// make sure account can be seen by OpenTasks
|
||||||
@ -67,7 +64,6 @@ class TasksSyncAdapterService: SyncAdapterService() {
|
|||||||
if (!extras.containsKey(ContentResolver.SYNC_EXTRAS_MANUAL) && !checkSyncConditions(accountSettings))
|
if (!extras.containsKey(ContentResolver.SYNC_EXTRAS_MANUAL) && !checkSyncConditions(accountSettings))
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
RefreshCollections(account, CollectionInfo.Type.TASKS).run()
|
RefreshCollections(account, CollectionInfo.Type.TASKS).run()
|
||||||
|
|
||||||
updateLocalTaskLists(taskProvider, account, accountSettings)
|
updateLocalTaskLists(taskProvider, account, accountSettings)
|
||||||
@ -80,38 +76,6 @@ class TasksSyncAdapterService: SyncAdapterService() {
|
|||||||
it.performSync()
|
it.performSync()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e: Exceptions.ServiceUnavailableException) {
|
|
||||||
syncResult.stats.numIoExceptions++
|
|
||||||
syncResult.delayUntil = if (e.retryAfter > 0) e.retryAfter else Constants.DEFAULT_RETRY_DELAY
|
|
||||||
} catch (e: Exceptions.IgnorableHttpException) {
|
|
||||||
// Ignore
|
|
||||||
} catch (e: Exception) {
|
|
||||||
if (e is SQLiteException) {
|
|
||||||
Logger.log.log(Level.SEVERE, "Couldn't prepare local task list", e)
|
|
||||||
syncResult.databaseError = true
|
|
||||||
}
|
|
||||||
|
|
||||||
val syncPhase = R.string.sync_phase_journals
|
|
||||||
val title = context.getString(R.string.sync_error_tasks, account.name)
|
|
||||||
|
|
||||||
notificationManager.setThrowable(e)
|
|
||||||
|
|
||||||
val detailsIntent = notificationManager.detailsIntent
|
|
||||||
detailsIntent.putExtra(Constants.KEY_ACCOUNT, account)
|
|
||||||
if (e !is Exceptions.UnauthorizedException) {
|
|
||||||
detailsIntent.putExtra(DebugInfoActivity.KEY_AUTHORITY, authority)
|
|
||||||
detailsIntent.putExtra(DebugInfoActivity.KEY_PHASE, syncPhase)
|
|
||||||
}
|
|
||||||
|
|
||||||
notificationManager.notify(title, context.getString(syncPhase))
|
|
||||||
} catch (e: OutOfMemoryError) {
|
|
||||||
val syncPhase = R.string.sync_phase_journals
|
|
||||||
val title = context.getString(R.string.sync_error_tasks, account.name)
|
|
||||||
notificationManager.setThrowable(e)
|
|
||||||
val detailsIntent = notificationManager.detailsIntent
|
|
||||||
detailsIntent.putExtra(Constants.KEY_ACCOUNT, account)
|
|
||||||
notificationManager.notify(title, context.getString(syncPhase))
|
|
||||||
}
|
|
||||||
|
|
||||||
Logger.log.info("Task sync complete")
|
Logger.log.info("Task sync complete")
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user