diff --git a/app/src/main/kotlin/at/bitfire/davdroid/resource/LocalAddressBook.kt b/app/src/main/kotlin/at/bitfire/davdroid/resource/LocalAddressBook.kt index 015f93f2..a9d531df 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/resource/LocalAddressBook.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/resource/LocalAddressBook.kt @@ -128,19 +128,22 @@ open class LocalAddressBook( * Finds and returns the main account of the given address book's account (sub-account) * * @param account the address book account to find the main account for - * @return the associated main account - * @throws IllegalArgumentException if the given account is not a address book account or does not have a main account + * + * @return the associated main account, `null` if none can be found (e.g. when main account has been deleted) + * + * @throws IllegalArgumentException when [account] is not an address book account */ - fun mainAccount(context: Context, account: Account): Account = + fun mainAccount(context: Context, account: Account): Account? = if (account.type == context.getString(R.string.account_type_address_book)) { val manager = AccountManager.get(context) val accountName = manager.getUserData(account, USER_DATA_MAIN_ACCOUNT_NAME) val accountType = manager.getUserData(account, USER_DATA_MAIN_ACCOUNT_TYPE) - if (accountName == null || accountType == null) - throw IllegalArgumentException("Address book account does not have a main account") - Account(accountName, accountType) + if (accountName != null && accountType != null) + Account(accountName, accountType) + else + null } else - throw IllegalArgumentException("Account is not an address book account") + throw IllegalArgumentException("$account is not an address book account") } @@ -157,7 +160,7 @@ open class LocalAddressBook( * but if it is enabled, [findDirty] will find dirty [LocalContact]s and [LocalGroup]s. */ open val groupMethod: GroupMethod by lazy { - val accountSettings = AccountSettings(context, mainAccount) + val accountSettings = AccountSettings(context, requireMainAccount()) accountSettings.getGroupMethod() } val includeGroups @@ -169,7 +172,7 @@ open class LocalAddressBook( * * @throws IllegalArgumentException when [account] is not an address book account or when no main account is assigned */ - open var mainAccount: Account + open var mainAccount: Account? get() { _mainAccount?.let { return it } @@ -178,6 +181,9 @@ open class LocalAddressBook( return result } set(newMainAccount) { + if (newMainAccount == null) + throw IllegalArgumentException("Main account must not be null") + AccountManager.get(context).let { accountManager -> accountManager.setAndVerifyUserData(account, USER_DATA_MAIN_ACCOUNT_NAME, newMainAccount.name) accountManager.setAndVerifyUserData(account, USER_DATA_MAIN_ACCOUNT_TYPE, newMainAccount.type) @@ -185,6 +191,8 @@ open class LocalAddressBook( _mainAccount = newMainAccount } + fun requireMainAccount(): Account = + mainAccount ?: throw IllegalArgumentException("No main account assigned to address book $account") var url: String get() = AccountManager.get(context).getUserData(account, USER_DATA_URL) @@ -236,7 +244,7 @@ open class LocalAddressBook( * @param forceReadOnly `true`: set the address book to "force read-only"; `false`: determine read-only flag from [info] */ fun update(info: Collection, forceReadOnly: Boolean) { - val newAccountName = accountName(mainAccount, info) + val newAccountName = accountName(requireMainAccount(), info) if (account.name != newAccountName) { // no need to re-assign contacts to new account, because they will be deleted by contacts provider in any case diff --git a/app/src/main/kotlin/at/bitfire/davdroid/settings/AccountSettings.kt b/app/src/main/kotlin/at/bitfire/davdroid/settings/AccountSettings.kt index 43758884..e833dc2d 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/settings/AccountSettings.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/settings/AccountSettings.kt @@ -141,16 +141,18 @@ class AccountSettings( val account: Account init { - when (argAccount.type) { + account = when (argAccount.type) { context.getString(R.string.account_type_address_book) -> { /* argAccount is an address book account, which is not a main account. However settings are - stored in the main account, so resolve and use the main account instead. */ - account = LocalAddressBook.mainAccount(context, argAccount) + stored in the main account, so resolve and use the main account instead. */ + LocalAddressBook.mainAccount(context, argAccount) ?: throw IllegalArgumentException("Main account of $argAccount not found") } + context.getString(R.string.account_type) -> - account = argAccount + argAccount + else -> - throw IllegalArgumentException("Account type not supported") + throw IllegalArgumentException("Account type ${argAccount.type} not supported") } // synchronize because account migration must only be run one time diff --git a/app/src/main/kotlin/at/bitfire/davdroid/syncadapter/AccountsCleanupWorker.kt b/app/src/main/kotlin/at/bitfire/davdroid/syncadapter/AccountsCleanupWorker.kt index c25d9540..592dd208 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/syncadapter/AccountsCleanupWorker.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/syncadapter/AccountsCleanupWorker.kt @@ -75,8 +75,9 @@ class AccountsCleanupWorker @AssistedInject constructor( .map { addressBookAccount -> LocalAddressBook(context, addressBookAccount, null) } for (addressBook in addressBooks) { try { - if (!mainAccountNames.contains(addressBook.mainAccount.name)) - // the main account for this address book doesn't exist anymore + val mainAccount = addressBook.mainAccount + if (mainAccount == null || !mainAccountNames.contains(mainAccount.name)) + // the main account for this address book doesn't exist anymore addressBook.delete() } catch(e: Exception) { Logger.log.log(Level.SEVERE, "Couldn't delete address book account", e) diff --git a/app/src/main/kotlin/at/bitfire/davdroid/syncadapter/SyncManager.kt b/app/src/main/kotlin/at/bitfire/davdroid/syncadapter/SyncManager.kt index 97dec863..faace8b8 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/syncadapter/SyncManager.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/syncadapter/SyncManager.kt @@ -809,7 +809,7 @@ abstract class SyncManager, out CollectionType: L .setContentTitle(localCollection.title) .setContentText(message) .setStyle(NotificationCompat.BigTextStyle(builder).bigText(message)) - .setSubText(mainAccount.name) + .setSubText(mainAccount?.name) .setOnlyAlertOnce(true) .setContentIntent(PendingIntent.getActivity(context, 0, contentIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)) .setPriority(priority) @@ -863,7 +863,7 @@ abstract class SyncManager, out CollectionType: L builder .setSmallIcon(R.drawable.ic_warning_notify) .setContentTitle(notifyInvalidResourceTitle()) .setContentText(context.getString(R.string.sync_invalid_resources_ignoring)) - .setSubText(mainAccount.name) + .setSubText(mainAccount?.name) .setContentIntent(PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)) .setAutoCancel(true) .setOnlyAlertOnce(true)