14

I'm working on an Android app that uses the AccountManager to store accounts & credentials. One problem I've been having is that even though I pass in a bunch of String values to the AccountManager's addAccountExplicitly data bundle.

I have checked to make sure that the bundle is not empty and that it contains the values before adding the account. And most of the time this is the case, but every once in a while I get null when I query these values.

The null return values are more common after I've just deleted the account and re-added it.

I'm doing my query inside the onAccountsUpdated method of an OnAccountsUpdateListener implementation, so the account should be added and good to go, right?

Thanks for any help

AuthenticatorActivity

// in the AuthenticatorActivity
Bundle userData = new Bundle();
userData.put (k1, v1);
userData.put (k2, v2);
userData.put (k3, v3);
userData.put (k4, v4);
userData.put (k1, v1);

Account a = new Account ("acc name", "com.account.type");
AccountManager am = AccountManager.get(this);

OnAccountsUpdateListener listener = new OnAccountsUpdateListener() {

        @Override
        public void onAccountsUpdated(Account[] accounts) {
            Account mine = findAccount(accounts, account); // match account name
            notifySignedIn(mine); // tell the world you're signed in
            am.removeOnAccountsUpdatedListener(this);
        }
    };

am.addOnAccountsUpdatedListener(listener, handler, false);
am.addAccountExplicitly(a, "themostsecurepwintheworld", userData);

Some other thread

AccountManager am = AccountManager.get(mContext);
final string value2 = am.getUserData(mAccount, k2);

if (TextUtils.isEmpty(value2)) {
    Log.d("WTF", "value is empty");
}
copolii
  • 14,208
  • 10
  • 51
  • 80
  • There is way too much code to copy + pase, but I'll edit the question with some basic code. There is a lot of concurrency and threading, but everything is initiated via the _onAccountsUpdatedListener_. – copolii May 21 '12 at 00:58

4 Answers4

9

I am aware of one bug in Honeycomb plus that can cause your issue. If you try to getUserData of the account before it is registered all subsequent getUserData calls will return null.

If you look at the code. AccountManager has an in-memory cache that is backed by a sqlite database. Calling getUserData populates the in-memory cache userdata, even if it is not registered. If it is not registered it interprets that as no userdata. Registering an account only populates the database and does not invalidate the in-memory store.

This may be causing your issue.

The workaround is to remove the account before calling addAccountExplicitly.

Ya this issue sucks and is a HUGE bug in AccountManger IMO and allows third parties to essence DOS your app.

Bishnu
  • 853
  • 7
  • 11
  • Thanks. I've since re-engineered the code to get around it, but if I remember correctly it had been occurring on pre-honeycomb devices as well as ICS devices too (Nexus 1, Nexus S, HTC Evo, Samsung Skyrocket, and a few more). – copolii Aug 03 '12 at 21:33
  • call removeAccount on your account before calling addAccountExplicitly. Also check that account exists before calling getUserData – Bishnu Sep 18 '13 at 04:31
3

Are you using an HTC device with Android 4? I got many reports of this issue from users of my sync apps. All of them used an HTC device with SDK level 15.

Looks like an HTC bug to me.

Several users reported that issue vanished after a reboot.

Update: Meanwhile we found a proper workaround, see https://stackoverflow.com/a/29776224/1558654

Community
  • 1
  • 1
Marten
  • 3,802
  • 1
  • 17
  • 26
  • Earlier AccountsMangers were naively backed by a sqlite database (all calls read from disk). This was changed in HoneyComb, however the in-memory cache has bugs. Rebooting the device clears the in-memory cache and lets the device read from the disk (and hence the original user data that was set by the user). – Bishnu Jul 28 '12 at 04:10
  • I received about 25 reports of this issue from HTC users and **no** reports from non-HTC users. That doesn't sound like coincidence to me. – Marten Jul 28 '12 at 08:11
  • This wasn't limited to HTC devices. My main test device was a Nexus S running 2.3.7, CM7, 4.0.4, and CM9. It did occur to varying extents on other devices too. – copolii Aug 03 '12 at 21:36
  • It's still an issue on HTC sdk 17. works perfectly on a number of samsung devices. – Stimsoni Mar 30 '15 at 03:40
  • Found a solution. see my post here http://stackoverflow.com/questions/28691847/android-accountmanager-getuserdata-returns-null/29358630#29358630 – Stimsoni Mar 31 '15 at 00:41
0

I had a similar issue, but my problem turned out to be attempting to store a long userData value instead of a String. Converting my long to a string for storage, and parsing it into a long again when pulling it out did the trick for me.

Chris6647
  • 178
  • 1
  • 2
  • 13
0

One potential cause for this may be calling AccountManager.getUserData() on a background thread. The documentation says "It is safe to call this method from the main thread." Our app was calling AccountManager.getUserData() on a background thread, which usually worked fine, but apparently isn't guaranteed to work.

Jeff Lockhart
  • 5,379
  • 4
  • 36
  • 51