Commit 1ecd16c2 authored by rhi's avatar rhi 🐑
Browse files

Address books accounts: set initial user data twice for older Android versions

parent 1804c4af
Pipeline #67164372 passed with stages
in 7 minutes and 14 seconds
......@@ -51,9 +51,18 @@ class LocalAddressBook(
val accountManager = AccountManager.get(context)
val account = Account(accountName(mainAccount, info), context.getString(R.string.account_type_address_book))
if (!accountManager.addAccountExplicitly(account, null, initialUserData(mainAccount, info.url.toString())))
val userData = initialUserData(mainAccount, info.url.toString())
Logger.log.log(Level.INFO, "Creating local address book $account", userData)
if (!accountManager.addAccountExplicitly(account, null, userData))
throw IllegalStateException("Couldn't create address book account")
  • As a side note: I also tested it on real hardware with an older Samsung Smartphone running 6.0.1. I was not able to reproduce the problem there. @rfc2822 Have you based the version check on what I wrote in the forum post or did you independently verify it? I wonder whether it would be better to not check for a specific version and instead check if the main account user data is set or not?

  • If possible, I'd like to mark the hack as a hack, and version checks are quite useful for that. Also, we didn't receive any real-world reports (at least no ones that are clearly related to that), so it doesn't seem to be a real problem on modern devices.

    Version checks also have the advantage that when the minimum SDK is raised at some time in the future, all the old hacks can just be removed because they don't apply anymore. This helps keeping the code clean.

    If the problem however can be reproduced for more recent Android versions, the version check would have to be removed of course.

Please register or sign in to reply
// Android < 7 seems to lose the initial user data sometimes, so set it a second time
userData.keySet().forEach { key ->
accountManager.setUserData(account, key, userData.getString(key))
val addressBook = LocalAddressBook(context, account, provider)
ContentResolver.setSyncAutomatically(account, ContactsContract.AUTHORITY, true)
......@@ -130,7 +139,7 @@ class LocalAddressBook(
if (name != null && type != null)
return Account(name, type)
throw IllegalStateException("Address book doesn't exist anymore")
throw IllegalStateException("No main account assigned to address book account")
set(newMainAccount) {
  • With this patch applied, I can no longer reproduce the problem.

  • I now had user reports where users with Android 9 were also affect by this problem (addressbook accounts with missing user data / reference to the main account). I've applied a patch like this in a downstream product based on davx5-ose, which seems to solve the problem.

    From a117dc509f69c635999d065bdf239d823a465267 Mon Sep 17 00:00:00 2001
    From: Michael Biebl <>
    Date: Fri, 13 Dec 2019 18:58:46 +0100
    Subject: [PATCH] When creating an addressbook account, verify the stored user
    Checking for the Android version is too simplistic. Apparently this
    also happens with newer devices.
     .../davdroid/resource/LocalAddressBook.kt      | 18 ++++++++++++++++--
     1 file changed, 16 insertions(+), 2 deletions(-)
    diff --git a/app/src/main/java/at/bitfire/davdroid/resource/LocalAddressBook.kt b/app/src/main/java/at/bitfire/davdroid/resource/LocalAddressBook.kt
    index 9d170dad..5b5d992b 100644
    --- a/app/src/main/java/at/bitfire/davdroid/resource/LocalAddressBook.kt
    +++ b/app/src/main/java/at/bitfire/davdroid/resource/LocalAddressBook.kt
    @@ -47,6 +47,20 @@ class LocalAddressBook(
             const val USER_DATA_URL = "url"
             const val USER_DATA_READ_ONLY = "read_only"
    +        private fun verifyUserData(context: Context, account: Account, userData: Bundle): Boolean {
    +            val accountManager = AccountManager.get(context)
    +            var r = true
    +            userData.keySet().forEach { key ->
    +                val stored = accountManager.getUserData(account, key)
    +                val expected = userData.getString(key)
    +                if (stored != expected) {
    +                    Logger.log.warning("Stored user data \"${stored}\" differs from expected data \"${expected}\" for ${key}")
    +                    r = false
    +                }
    +            }
    +            return r
    +        }
             fun create(context: Context, provider: ContentProviderClient, mainAccount: Account, info: Collection): LocalAddressBook {
                 val accountManager = AccountManager.get(context)
    @@ -56,8 +70,8 @@ class LocalAddressBook(
                 if (!accountManager.addAccountExplicitly(account, null, userData))
                     throw IllegalStateException("Couldn't create address book account")
    -            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N)
    -                // Android < 7 seems to lose the initial user data sometimes, so set it a second time
    +            if (!verifyUserData(context, account, userData))
    +                // Android seems to lose the initial user data sometimes, so set it a second time if necessary
                     userData.keySet().forEach { key ->
                         accountManager.setUserData(account, key, userData.getString(key))

    I'm happy to submit a proper MR

  • Hi, thanks for the patch. We're currently preparing a better infrastructure for patches (including Contributors License Agreement [unfortunately we need that] and mentioning in the About dialog). I'll take the patch later.

Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment