From 674ea1eeca378189e42cdb6f337aa4049db2627a Mon Sep 17 00:00:00 2001 From: Tom Hacohen Date: Wed, 26 Apr 2017 20:40:52 +0100 Subject: [PATCH] Workaround Android account creation issue (ignoring userData) It seems like there's an issue with Android that sometimes the userData passed to addAccountExplicitly is not correctly set in the Android cache making it return null on subsequent fetches. It doesn't always happen because some cases clear the cache, however I can consistently trigger it by creating and deleting an account a few times in a row. --- .../com/etesync/syncadapter/AccountSettings.java | 16 ++++++++-------- .../syncadapter/resource/LocalAddressBook.java | 16 +++++++--------- .../ui/setup/SetupEncryptionFragment.java | 7 ++++--- 3 files changed, 19 insertions(+), 20 deletions(-) diff --git a/app/src/main/java/com/etesync/syncadapter/AccountSettings.java b/app/src/main/java/com/etesync/syncadapter/AccountSettings.java index 845a4de0..9eca2913 100644 --- a/app/src/main/java/com/etesync/syncadapter/AccountSettings.java +++ b/app/src/main/java/com/etesync/syncadapter/AccountSettings.java @@ -31,7 +31,6 @@ import com.etesync.syncadapter.model.CollectionInfo; import com.etesync.syncadapter.resource.LocalAddressBook; import com.etesync.syncadapter.utils.Base64; -import java.lang.reflect.Method; import java.net.URI; import java.net.URISyntaxException; import java.util.List; @@ -105,12 +104,11 @@ public class AccountSettings { } } - public static Bundle initialUserData(URI uri, String userName) { - Bundle bundle = new Bundle(); - bundle.putString(KEY_SETTINGS_VERSION, String.valueOf(CURRENT_VERSION)); - bundle.putString(KEY_USERNAME, userName); - bundle.putString(KEY_URI, uri.toString()); - return bundle; + // XXX: Workaround a bug in Android where passing a bundle to addAccountExplicitly doesn't work. + public static void setUserData(AccountManager accountManager, Account account, URI uri, String userName) { + accountManager.setUserData(account, KEY_SETTINGS_VERSION, String.valueOf(CURRENT_VERSION)); + accountManager.setUserData(account, KEY_USERNAME, userName); + accountManager.setUserData(account, KEY_URI, uri.toString()); } @@ -286,8 +284,10 @@ public class AccountSettings { info.displayName = account.name; App.log.log(Level.INFO, "Creating new address book account", url); Account addressBookAccount = new Account(LocalAddressBook.accountName(account, info), App.getAddressBookAccountType()); - if (!accountManager.addAccountExplicitly(addressBookAccount, null, LocalAddressBook.initialUserData(account, info.uid))) + if (!accountManager.addAccountExplicitly(addressBookAccount, null, null)) throw new ContactsStorageException("Couldn't create address book account"); + + LocalAddressBook.setUserData(accountManager, addressBookAccount, account, info.uid); LocalAddressBook addressBook = new LocalAddressBook(context, addressBookAccount, provider); // move contacts to new address book diff --git a/app/src/main/java/com/etesync/syncadapter/resource/LocalAddressBook.java b/app/src/main/java/com/etesync/syncadapter/resource/LocalAddressBook.java index 5a2f3108..44691e69 100644 --- a/app/src/main/java/com/etesync/syncadapter/resource/LocalAddressBook.java +++ b/app/src/main/java/com/etesync/syncadapter/resource/LocalAddressBook.java @@ -34,9 +34,7 @@ import com.etesync.syncadapter.App; import com.etesync.syncadapter.model.CollectionInfo; import com.etesync.syncadapter.model.JournalEntity; import com.etesync.syncadapter.utils.AndroidCompat; -import com.etesync.syncadapter.utils.Base64; -import java.io.ByteArrayOutputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.util.Collections; @@ -102,9 +100,10 @@ public class LocalAddressBook extends AndroidAddressBook implements LocalCollect AccountManager accountManager = AccountManager.get(context); Account account = new Account(accountName(mainAccount, info), App.getAddressBookAccountType()); - if (!accountManager.addAccountExplicitly(account, null, initialUserData(mainAccount, info.uid))) + if (!accountManager.addAccountExplicitly(account, null, null)) throw new ContactsStorageException("Couldn't create address book account"); + setUserData(accountManager, account, mainAccount, info.uid); LocalAddressBook addressBook = new LocalAddressBook(context, account, provider); addressBook.setMainAccount(mainAccount); addressBook.setURL(info.uid); @@ -360,12 +359,11 @@ public class LocalAddressBook extends AndroidAddressBook implements LocalCollect // SETTINGS - public static Bundle initialUserData(@NonNull Account mainAccount, @NonNull String url) { - Bundle bundle = new Bundle(3); - bundle.putString(USER_DATA_MAIN_ACCOUNT_NAME, mainAccount.name); - bundle.putString(USER_DATA_MAIN_ACCOUNT_TYPE, mainAccount.type); - bundle.putString(USER_DATA_URL, url); - return bundle; + // XXX: Workaround a bug in Android where passing a bundle to addAccountExplicitly doesn't work. + public static void setUserData(@NonNull AccountManager accountManager, @NonNull Account account, @NonNull Account mainAccount, @NonNull String url) { + accountManager.setUserData(account, USER_DATA_MAIN_ACCOUNT_NAME, mainAccount.name); + accountManager.setUserData(account, USER_DATA_MAIN_ACCOUNT_TYPE, mainAccount.type); + accountManager.setUserData(account, USER_DATA_URL, url); } public Account getMainAccount() throws ContactsStorageException { diff --git a/app/src/main/java/com/etesync/syncadapter/ui/setup/SetupEncryptionFragment.java b/app/src/main/java/com/etesync/syncadapter/ui/setup/SetupEncryptionFragment.java index 2db72cf4..e3e9a45a 100644 --- a/app/src/main/java/com/etesync/syncadapter/ui/setup/SetupEncryptionFragment.java +++ b/app/src/main/java/com/etesync/syncadapter/ui/setup/SetupEncryptionFragment.java @@ -166,13 +166,14 @@ public class SetupEncryptionFragment extends DialogFragment implements LoaderMan Account account = new Account(accountName, App.getAccountType()); // create Android account - Bundle userData = AccountSettings.initialUserData(config.url, config.userName); - App.log.log(Level.INFO, "Creating Android account with initial config", new Object[] { account, userData }); + App.log.log(Level.INFO, "Creating Android account with initial config", new Object[] { account, config.userName, config.url }); AccountManager accountManager = AccountManager.get(getContext()); - if (!accountManager.addAccountExplicitly(account, config.password, userData)) + if (!accountManager.addAccountExplicitly(account, config.password, null)) return false; + AccountSettings.setUserData(accountManager, account, config.url, config.userName); + // add entries for account to service DB App.log.log(Level.INFO, "Writing account configuration to database", config); try {