Android , Development

Android AccountManager - Handling the deprecation of removeAccount() in API 22

February 27, 2018

The Situation

In Android API level 22 (Lollipop MR1), the method

<span class="n">AccountManager</span><span class="o">.</span><span class="na">removeAccount</span><span class="o">(</span><span class="n">Account</span><span class="o">,</span> <span class="n">AccountManagerCallback</span><span class="o"><</span><span class="n">Boolean</span><span class="o">>,</span> <span class="n">Handler</span><span class="o">)</span> <span class="c1">// old method</span>

was deprecated. The SDK documentation says to instead use this method,

<span class="n">AccountManager</span><span class="o">.</span><span class="na">removeAccount</span><span class="o">(</span><span class="n">Account</span><span class="o">,</span> <span class="n">Activity</span><span class="o">,</span> <span class="n">AccountManagerCallback</span><span class="o"><</span><span class="n">Bundle</span><span class="o">>,</span> <span class="n">Handler</span><span class="o">)</span> <span class="c1">// new method</span>

added in the same API level.

AccountManager.removeAccount() is a method used to remove an account tracked by the Android OS for your app, and needs to be called when the user logs out of their account in your app.

You’ll want to be a prudent developer and migrate away from deprecated methods, but if your minSdkVersion is less than 22, you’ll need to resolve this seemingly large discrepancy between these two AccountManager methods. To accomplish this, we’ll start with a draft of a utility method that will call one or the other depending on what version of Android your app is running in, with an argument signature that matches the new version of the removeAccount() method.

<span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">removeAccount</span><span class="o">(</span>
 <span class="n">Account</span> <span class="n">account</span><span class="o">,</span>
 <span class="n">Activity</span> <span class="n">activity</span><span class="o">,</span>
 <span class="kd">final</span> <span class="n">AccountManagerCallback</span><span class="o"><</span><span class="n">Bundle</span><span class="o">></span> <span class="n">callback</span><span class="o">,</span>
 <span class="n">Handler</span> <span class="n">handler</span>
<span class="o">)</span> <span class="o">{</span>
 <span class="n">AccountManager</span> <span class="n">accountManager</span> <span class="o">=</span> <span class="n">AccountManager</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="n">activity</span><span class="o">);</span>

 <span class="k">if</span> <span class="o">(</span><span class="n">Build</span><span class="o">.</span><span class="na">VERSION</span><span class="o">.</span><span class="na">SDK_INT</span> <span class="o">>=</span> <span class="n">Build</span><span class="o">.</span><span class="na">VERSION_CODES</span><span class="o">.</span><span class="na">LOLLIPOP_MR1</span><span class="o">)</span> <span class="o">{</span>
 <span class="c1">// API 22 and above</span>
 <span class="n">accountManager</span><span class="o">.</span><span class="na">removeAccount</span><span class="o">(</span><span class="n">account</span><span class="o">,</span> <span class="n">activity</span><span class="o">,</span> <span class="n">callback</span><span class="o">,</span> <span class="n">handler</span><span class="o">);</span>
 <span class="o">}</span> <span class="k">else</span> <span class="o">{</span>
 <span class="c1">// API 21 and below</span>
 <span class="n">accountManager</span><span class="o">.</span><span class="na">removeAccount</span><span class="o">(</span><span class="n">account</span><span class="o">,</span> <span class="cm">/* AccountManagerCallback<boolean> */</boolean></span><span class="o">,</span> <span class="n">handler</span><span class="o">);</span>
 <span class="c1">// we need to figure out what to do for the second argument</span>
 <span class="o">}</span>
<span class="o">}</span>

The Discrepancy

The big difference between these two methods is the AccountManagerCallback<boolean></boolean> and AccountManagerCallback<bundle></bundle> arguments, both callbacks that asynchronously return an AccountManagerFuture<!--?-->. In the case of the former,

<span class="k">new</span> <span class="n">AccountManagerCallback</span><span class="o"><</span><span class="n">Boolean</span><span class="o">>()</span> <span class="o">{</span>
 <span class="nd">@Override</span>
 <span class="kd">public</span> <span class="kt">void</span> <span class="nf">run</span><span class="o">(</span><span class="n">AccountManagerFuture</span><span class="o"><</span><span class="n">Boolean</span><span class="o">></span> <span class="n">future</span><span class="o">)</span> <span class="o">{</span>
 <span class="c1">// get the success status of the account manager operation from `future`</span>
 <span class="n">Boolean</span> <span class="n">result</span> <span class="o">=</span> <span class="n">future</span><span class="o">.</span><span class="na">getResult</span><span class="o">();</span>

 <span class="c1">// do something with the result...</span>
 <span class="o">}</span>
<span class="o">}</span>

How do we go from this Boolean to a Bundle? The answer lies in what the new removeAccount() method returns in its AccountManagerCallback<bundle></bundle> callback. If you were to execute the new removeAccount() method, you would find that the AccountManagerCallback<bundle></bundle> asynchronously returns a Bundle that contains AccountManager.KEY_BOOLEAN_RESULT and a Boolean as a key/value pair. The Boolean value returned indicates the success or failure of the account removal operation. We can take the Boolean result from the old callback and adapt it to the new callback.

<span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">removeAccount</span><span class="o">(</span>
 <span class="n">Account</span> <span class="n">account</span><span class="o">,</span>
 <span class="n">Activity</span> <span class="n">activity</span><span class="o">,</span>
 <span class="kd">final</span> <span class="n">AccountManagerCallback</span><span class="o"><</span><span class="n">Bundle</span><span class="o">></span> <span class="n">callback</span><span class="o">,</span>
 <span class="n">Handler</span> <span class="n">handler</span>
<span class="o">)</span> <span class="o">{</span>
 <span class="n">AccountManager</span> <span class="n">accountManager</span> <span class="o">=</span> <span class="n">AccountManager</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="n">activity</span><span class="o">);</span>

 <span class="k">if</span> <span class="o">(</span><span class="n">Build</span><span class="o">.</span><span class="na">VERSION</span><span class="o">.</span><span class="na">SDK_INT</span> <span class="o">>=</span> <span class="n">Build</span><span class="o">.</span><span class="na">VERSION_CODES</span><span class="o">.</span><span class="na">LOLLIPOP_MR1</span><span class="o">)</span> <span class="o">{</span>
 <span class="c1">// API 22 and above</span>
 <span class="n">accountManager</span><span class="o">.</span><span class="na">removeAccount</span><span class="o">(</span><span class="n">account</span><span class="o">,</span> <span class="n">activity</span><span class="o">,</span> <span class="n">callback</span><span class="o">,</span> <span class="n">handler</span><span class="o">);</span>
 <span class="o">}</span> <span class="k">else</span> <span class="o">{</span>
 <span class="c1">// API 21 and below</span>
 <span class="n">accountManager</span><span class="o">.</span><span class="na">removeAccount</span><span class="o">(</span>
 <span class="n">account</span><span class="o">,</span>
 <span class="k">new</span> <span class="n">AccountManagerCallback</span><span class="o"><</span><span class="n">Boolean</span><span class="o">>()</span> <span class="o">{</span>
 <span class="nd">@Override</span>
 <span class="kd">public</span> <span class="kt">void</span> <span class="nf">run</span><span class="o">(</span><span class="kd">final</span> <span class="n">AccountManagerFuture</span><span class="o"><</span><span class="n">Boolean</span><span class="o">></span> <span class="n">future</span><span class="o">)</span> <span class="o">{</span>
 <span class="c1">// call our AccountManagerCallback<bundle> callback and put the Boolean result from `future`</bundle></span>
 <span class="c1">// into a Bundle in the form that the system is expecting</span>
 <span class="n">callback</span><span class="o">.</span><span class="na">run</span><span class="o">(</span><span class="k">new</span> <span class="n">AccountManagerFuture</span><span class="o"><</span><span class="n">Bundle</span><span class="o">>()</span> <span class="o">{</span>
 <span class="nd">@Override</span>
 <span class="kd">public</span> <span class="n">Bundle</span> <span class="nf">getResult</span><span class="o">()</span>
 <span class="kd">throws</span> <span class="n">OperationCanceledException</span><span class="o">,</span> <span class="n">IOException</span><span class="o">,</span> <span class="n">AuthenticatorException</span>
 <span class="o">{</span>
 <span class="n">Bundle</span> <span class="n">result</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Bundle</span><span class="o">();</span>
 <span class="n">result</span><span class="o">.</span><span class="na">putBoolean</span><span class="o">(</span><span class="n">AccountManager</span><span class="o">.</span><span class="na">KEY_BOOLEAN_RESULT</span><span class="o">,</span> <span class="n">future</span><span class="o">.</span><span class="na">getResult</span><span class="o">());</span>
 <span class="k">return</span> <span class="n">result</span><span class="o">;</span>
 <span class="o">}</span>
 <span class="o">});</span>
 <span class="o">}</span>
 <span class="o">},</span>
 <span class="n">handler</span>
 <span class="o">);</span>
 <span class="o">}</span>
<span class="o">}</span>

The AccountManagerCallback<boolean></boolean> interface has a few other methods that also need to be implemented and adapted to an AccountManagerCallback<bundle></bundle> callback.

<span class="k">new</span> <span class="n">AccountManagerCallback</span><span class="o"><</span><span class="n">Boolean</span><span class="o">>()</span> <span class="o">{</span>
 <span class="nd">@Override</span>
 <span class="kd">public</span> <span class="kt">void</span> <span class="nf">run</span><span class="o">(</span><span class="kd">final</span> <span class="n">AccountManagerFuture</span><span class="o"><</span><span class="n">Boolean</span><span class="o">></span> <span class="n">future</span><span class="o">)</span> <span class="o">{</span>
 <span class="k">if</span> <span class="o">(</span><span class="n">callback</span> <span class="o">==</span> <span class="kc">null</span><span class="o">)</span> <span class="o">{</span>
 <span class="k">return</span><span class="o">;</span>
 <span class="o">}</span>

 <span class="n">callback</span><span class="o">.</span><span class="na">run</span><span class="o">(</span><span class="k">new</span> <span class="n">AccountManagerFuture</span><span class="o"><</span><span class="n">Bundle</span><span class="o">>()</span> <span class="o">{</span>
 <span class="nd">@Override</span>
 <span class="kd">public</span> <span class="kt">boolean</span> <span class="nf">cancel</span><span class="o">(</span><span class="kt">boolean</span> <span class="n">mayInterruptIfRunning</span><span class="o">)</span> <span class="o">{</span>
 <span class="k">return</span> <span class="n">future</span><span class="o">.</span><span class="na">cancel</span><span class="o">(</span><span class="n">mayInterruptIfRunning</span><span class="o">);</span>
 <span class="o">}</span>

 <span class="nd">@Override</span>
 <span class="kd">public</span> <span class="kt">boolean</span> <span class="nf">isCancelled</span><span class="o">()</span> <span class="o">{</span>
 <span class="k">return</span> <span class="n">future</span><span class="o">.</span><span class="na">isCancelled</span><span class="o">();</span>
 <span class="o">}</span>

 <span class="nd">@Override</span>
 <span class="kd">public</span> <span class="kt">boolean</span> <span class="nf">isDone</span><span class="o">()</span> <span class="o">{</span>
 <span class="k">return</span> <span class="n">future</span><span class="o">.</span><span class="na">isDone</span><span class="o">();</span>
 <span class="o">}</span>

 <span class="nd">@Override</span>
 <span class="kd">public</span> <span class="n">Bundle</span> <span class="nf">getResult</span><span class="o">()</span>
 <span class="kd">throws</span> <span class="n">OperationCanceledException</span><span class="o">,</span> <span class="n">IOException</span><span class="o">,</span> <span class="n">AuthenticatorException</span>
 <span class="o">{</span>
 <span class="n">Bundle</span> <span class="n">result</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Bundle</span><span class="o">();</span>
 <span class="n">result</span><span class="o">.</span><span class="na">putBoolean</span><span class="o">(</span><span class="n">AccountManager</span><span class="o">.</span><span class="na">KEY_BOOLEAN_RESULT</span><span class="o">,</span> <span class="n">future</span><span class="o">.</span><span class="na">getResult</span><span class="o">());</span>
 <span class="k">return</span> <span class="n">result</span><span class="o">;</span>
 <span class="o">}</span>

 <span class="nd">@Override</span>
 <span class="kd">public</span> <span class="n">Bundle</span> <span class="nf">getResult</span><span class="o">(</span><span class="kt">long</span> <span class="n">timeout</span><span class="o">,</span> <span class="n">TimeUnit</span> <span class="n">unit</span><span class="o">)</span>
 <span class="kd">throws</span> <span class="n">OperationCanceledException</span><span class="o">,</span> <span class="n">IOException</span><span class="o">,</span> <span class="n">AuthenticatorException</span>
 <span class="o">{</span>
 <span class="n">Bundle</span> <span class="n">result</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Bundle</span><span class="o">();</span>
 <span class="n">result</span><span class="o">.</span><span class="na">putBoolean</span><span class="o">(</span><span class="n">AccountManager</span><span class="o">.</span><span class="na">KEY_BOOLEAN_RESULT</span><span class="o">,</span> <span class="n">future</span><span class="o">.</span><span class="na">getResult</span><span class="o">(</span><span class="n">timeout</span><span class="o">,</span> <span class="n">unit</span><span class="o">));</span>
 <span class="k">return</span> <span class="n">result</span><span class="o">;</span>
 <span class="o">}</span>
 <span class="o">});</span>
 <span class="o">}</span>
<span class="o">}</span>

We’ve taken the results of the old-style callback and “forwarded” them to the new-style callback. Since the future.getResult() method can throw OperationCanceledException, IOException, and AuthenticatorException, we’ll “forward” them by passing them up to be handled by the new-style callback.

Putting it all together

Putting all of this together results in a utility method that resolves the discrepancy between the old and new way of removing an account from the system.

<span class="cm">/*
 * In API 22 (LOLLIPOP_MR1),
 * AccountManager.removeAccount(Account, Activity, AccountManagerCallback<bundle>, Handler) was added, and
 * AccountManager.removeAccount(Account, AccountManagerCallback<boolean>, Handler) was deprecated.
 *
 * To resolve this when running on a pre-22 device, call the old .removeAccount(), get the Boolean result,
 * put it in a Bundle using key AccountManager.KEY_BOOLEAN_RESULT,
 * then call AccountManagerCallback<bundle> callback.run() with a new AccountManagerFuture<bundle>
 * that returns this Bundle.
 */</bundle></bundle></boolean></bundle></span>
<span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">removeAccount</span><span class="o">(</span>
 <span class="nd">@NonNull</span> <span class="n">Account</span> <span class="n">account</span><span class="o">,</span>
 <span class="nd">@NonNull</span> <span class="n">Activity</span> <span class="n">activity</span><span class="o">,</span>
 <span class="nd">@Nullable</span> <span class="kd">final</span> <span class="n">AccountManagerCallback</span><span class="o"><</span><span class="n">Bundle</span><span class="o">></span> <span class="n">callback</span><span class="o">,</span>
 <span class="nd">@Nullable</span> <span class="n">Handler</span> <span class="n">handler</span>
<span class="o">)</span> <span class="o">{</span>
 <span class="n">AccountManager</span> <span class="n">accountManager</span> <span class="o">=</span> <span class="n">AccountManager</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="n">activity</span><span class="o">);</span>

 <span class="k">if</span> <span class="o">(</span><span class="n">Build</span><span class="o">.</span><span class="na">VERSION</span><span class="o">.</span><span class="na">SDK_INT</span> <span class="o">>=</span> <span class="n">Build</span><span class="o">.</span><span class="na">VERSION_CODES</span><span class="o">.</span><span class="na">LOLLIPOP_MR1</span><span class="o">)</span> <span class="o">{</span>
 <span class="n">accountManager</span><span class="o">.</span><span class="na">removeAccount</span><span class="o">(</span><span class="n">account</span><span class="o">,</span> <span class="n">activity</span><span class="o">,</span> <span class="n">callback</span><span class="o">,</span> <span class="n">handler</span><span class="o">);</span>
 <span class="o">}</span> <span class="k">else</span> <span class="o">{</span>
 <span class="c1">//noinspection deprecation - we don't need our IDE to warn us that this is deprecated</span>
 <span class="n">accountManager</span><span class="o">.</span><span class="na">removeAccount</span><span class="o">(</span>
 <span class="n">account</span><span class="o">,</span>
 <span class="k">new</span> <span class="n">AccountManagerCallback</span><span class="o"><</span><span class="n">Boolean</span><span class="o">>()</span> <span class="o">{</span>
 <span class="nd">@Override</span>
 <span class="kd">public</span> <span class="kt">void</span> <span class="nf">run</span><span class="o">(</span><span class="kd">final</span> <span class="n">AccountManagerFuture</span><span class="o"><</span><span class="n">Boolean</span><span class="o">></span> <span class="n">future</span><span class="o">)</span> <span class="o">{</span>
 <span class="k">if</span> <span class="o">(</span><span class="n">callback</span> <span class="o">==</span> <span class="kc">null</span><span class="o">)</span> <span class="o">{</span>
 <span class="k">return</span><span class="o">;</span>
 <span class="o">}</span>

 <span class="n">callback</span><span class="o">.</span><span class="na">run</span><span class="o">(</span><span class="k">new</span> <span class="n">AccountManagerFuture</span><span class="o"><</span><span class="n">Bundle</span><span class="o">>()</span> <span class="o">{</span>
 <span class="nd">@Override</span>
 <span class="kd">public</span> <span class="kt">boolean</span> <span class="nf">cancel</span><span class="o">(</span><span class="kt">boolean</span> <span class="n">mayInterruptIfRunning</span><span class="o">)</span> <span class="o">{</span>
 <span class="k">return</span> <span class="n">future</span><span class="o">.</span><span class="na">cancel</span><span class="o">(</span><span class="n">mayInterruptIfRunning</span><span class="o">);</span>
 <span class="o">}</span>

 <span class="nd">@Override</span>
 <span class="kd">public</span> <span class="kt">boolean</span> <span class="nf">isCancelled</span><span class="o">()</span> <span class="o">{</span>
 <span class="k">return</span> <span class="n">future</span><span class="o">.</span><span class="na">isCancelled</span><span class="o">();</span>
 <span class="o">}</span>

 <span class="nd">@Override</span>
 <span class="kd">public</span> <span class="kt">boolean</span> <span class="nf">isDone</span><span class="o">()</span> <span class="o">{</span>
 <span class="k">return</span> <span class="n">future</span><span class="o">.</span><span class="na">isDone</span><span class="o">();</span>
 <span class="o">}</span>

 <span class="nd">@Override</span>
 <span class="kd">public</span> <span class="n">Bundle</span> <span class="nf">getResult</span><span class="o">()</span>
 <span class="kd">throws</span> <span class="n">OperationCanceledException</span><span class="o">,</span> <span class="n">IOException</span><span class="o">,</span> <span class="n">AuthenticatorException</span>
 <span class="o">{</span>
 <span class="n">Bundle</span> <span class="n">result</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Bundle</span><span class="o">();</span>
 <span class="n">result</span><span class="o">.</span><span class="na">putBoolean</span><span class="o">(</span><span class="n">AccountManager</span><span class="o">.</span><span class="na">KEY_BOOLEAN_RESULT</span><span class="o">,</span> <span class="n">future</span><span class="o">.</span><span class="na">getResult</span><span class="o">());</span>
 <span class="k">return</span> <span class="n">result</span><span class="o">;</span>
 <span class="o">}</span>

 <span class="nd">@Override</span>
 <span class="kd">public</span> <span class="n">Bundle</span> <span class="nf">getResult</span><span class="o">(</span><span class="kt">long</span> <span class="n">timeout</span><span class="o">,</span> <span class="n">TimeUnit</span> <span class="n">unit</span><span class="o">)</span>
 <span class="kd">throws</span> <span class="n">OperationCanceledException</span><span class="o">,</span> <span class="n">IOException</span><span class="o">,</span> <span class="n">AuthenticatorException</span>
 <span class="o">{</span>
 <span class="n">Bundle</span> <span class="n">result</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Bundle</span><span class="o">();</span>
 <span class="n">result</span><span class="o">.</span><span class="na">putBoolean</span><span class="o">(</span><span class="n">AccountManager</span><span class="o">.</span><span class="na">KEY_BOOLEAN_RESULT</span><span class="o">,</span> <span class="n">future</span><span class="o">.</span><span class="na">getResult</span><span class="o">(</span><span class="n">timeout</span><span class="o">,</span> <span class="n">unit</span><span class="o">));</span>
 <span class="k">return</span> <span class="n">result</span><span class="o">;</span>
 <span class="o">}</span>
 <span class="o">});</span>
 <span class="o">}</span>
 <span class="o">},</span>
 <span class="n">handler</span>
 <span class="o">);</span>
 <span class="o">}</span>
<span class="o">}</span>

You can find this code in this Github gist.

Now when you need to remove an account, you can just call

<span class="n">removeAccount</span><span class="o">(</span>
 <span class="n">account</span><span class="o">,</span>
 <span class="n">activity</span><span class="o">,</span>
 <span class="k">new</span> <span class="n">AccountManagerCallback</span><span class="o"><</span><span class="n">Bundle</span><span class="o">>()</span> <span class="o">{</span>
 <span class="nd">@Override</span>
 <span class="kd">public</span> <span class="kt">void</span> <span class="nf">run</span><span class="o">(</span><span class="n">AccountManagerFuture</span><span class="o"><</span><span class="n">Bundle</span><span class="o">></span> <span class="n">future</span><span class="o">)</span> <span class="o">{</span>
 <span class="k">try</span> <span class="o">{</span>
 <span class="n">Bundle</span> <span class="n">result</span> <span class="o">=</span> <span class="n">future</span><span class="o">.</span><span class="na">getResult</span><span class="o">();</span>
 <span class="kt">boolean</span> <span class="n">success</span> <span class="o">=</span> <span class="n">result</span><span class="o">.</span><span class="na">getBoolean</span><span class="o">(</span><span class="n">AccountManager</span><span class="o">.</span><span class="na">KEY_BOOLEAN_RESULT</span><span class="o">);</span>

 <span class="k">if</span> <span class="o">(</span><span class="n">success</span><span class="o">)</span> <span class="o">{</span>
 <span class="c1">// the account was successfully removed</span>
 <span class="o">}</span> <span class="k">else</span> <span class="o">{</span>
 <span class="c1">// failed to remove the account</span>
 <span class="o">}</span>
 <span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="n">OperationCanceledException</span> <span class="o">|</span> <span class="n">IOException</span> <span class="o">|</span> <span class="n">AuthenticatorException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
 <span class="c1">// something went wrong</span>
 <span class="o">}</span>
 <span class="o">}</span>
 <span class="o">},</span>
 <span class="kc">null</span>
<span class="o">);</span>

Let’s do it with Java 8 Lambdas

If you’re using the latest version of the Android Gradle plugin (as of this writing) in your build.gradle file

<span class="n">buildscript</span> <span class="o">{</span>
 <span class="o">...</span>

 <span class="n">dependencies</span> <span class="o">{</span>
 <span class="n">classpath</span> <span class="s1">'com.android.tools.build:gradle:3.0.1'</span>
 <span class="o">...</span>
 <span class="o">}</span>
<span class="o">}</span>

and using Java 8 source compatibility

<span class="n">compileOptions</span> <span class="o">{</span>
 <span class="n">sourceCompatibility</span> <span class="n">JavaVersion</span><span class="o">.</span><span class="na">VERSION_1_8</span>
 <span class="n">targetCompatibility</span> <span class="n">JavaVersion</span><span class="o">.</span><span class="na">VERSION_1_8</span>
<span class="o">}</span>

then you can write the same method using lambdas.

<span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">removeAccount</span><span class="o">(</span>
 <span class="nd">@NonNull</span> <span class="n">Account</span> <span class="n">account</span><span class="o">,</span>
 <span class="nd">@NonNull</span> <span class="n">Activity</span> <span class="n">activity</span><span class="o">,</span>
 <span class="nd">@Nullable</span> <span class="kd">final</span> <span class="n">AccountManagerCallback</span><span class="o"><</span><span class="n">Bundle</span><span class="o">></span> <span class="n">callback</span><span class="o">,</span>
 <span class="nd">@Nullable</span> <span class="n">Handler</span> <span class="n">handler</span>
<span class="o">)</span> <span class="o">{</span>
 <span class="n">AccountManager</span> <span class="n">accountManager</span> <span class="o">=</span> <span class="n">AccountManager</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="n">activity</span><span class="o">);</span>

 <span class="k">if</span> <span class="o">(</span><span class="n">Build</span><span class="o">.</span><span class="na">VERSION</span><span class="o">.</span><span class="na">SDK_INT</span> <span class="o">>=</span> <span class="n">Build</span><span class="o">.</span><span class="na">VERSION_CODES</span><span class="o">.</span><span class="na">LOLLIPOP_MR1</span><span class="o">)</span> <span class="o">{</span>
 <span class="n">accountManager</span><span class="o">.</span><span class="na">removeAccount</span><span class="o">(</span><span class="n">account</span><span class="o">,</span> <span class="n">activity</span><span class="o">,</span> <span class="n">callback</span><span class="o">,</span> <span class="n">handler</span><span class="o">);</span>
 <span class="o">}</span> <span class="k">else</span> <span class="o">{</span>
 <span class="c1">//noinspection deprecation - we don't need our IDE to warn us that this is deprecated</span>
 <span class="n">accountManager</span><span class="o">.</span><span class="na">removeAccount</span><span class="o">(</span>
 <span class="n">account</span><span class="o">,</span>
 <span class="n">future</span> <span class="o">-></span> <span class="o">{</span>
 <span class="k">if</span> <span class="o">(</span><span class="n">callback</span> <span class="o">==</span> <span class="kc">null</span><span class="o">)</span> <span class="o">{</span>
 <span class="k">return</span><span class="o">;</span>
 <span class="o">}</span>

 <span class="n">callback</span><span class="o">.</span><span class="na">run</span><span class="o">(</span><span class="k">new</span> <span class="n">AccountManagerFuture</span><span class="o"><</span><span class="n">Bundle</span><span class="o">>()</span> <span class="o">{</span>
 <span class="nd">@Override</span>
 <span class="kd">public</span> <span class="kt">boolean</span> <span class="nf">cancel</span><span class="o">(</span><span class="kt">boolean</span> <span class="n">mayInterruptIfRunning</span><span class="o">)</span> <span class="o">{</span>
 <span class="k">return</span> <span class="n">future</span><span class="o">.</span><span class="na">cancel</span><span class="o">(</span><span class="n">mayInterruptIfRunning</span><span class="o">);</span>
 <span class="o">}</span>

 <span class="nd">@Override</span>
 <span class="kd">public</span> <span class="kt">boolean</span> <span class="nf">isCancelled</span><span class="o">()</span> <span class="o">{</span>
 <span class="k">return</span> <span class="n">future</span><span class="o">.</span><span class="na">isCancelled</span><span class="o">();</span>
 <span class="o">}</span>

 <span class="nd">@Override</span>
 <span class="kd">public</span> <span class="kt">boolean</span> <span class="nf">isDone</span><span class="o">()</span> <span class="o">{</span>
 <span class="k">return</span> <span class="n">future</span><span class="o">.</span><span class="na">isDone</span><span class="o">();</span>
 <span class="o">}</span>

 <span class="nd">@Override</span>
 <span class="kd">public</span> <span class="n">Bundle</span> <span class="nf">getResult</span><span class="o">()</span>
 <span class="kd">throws</span> <span class="n">OperationCanceledException</span><span class="o">,</span> <span class="n">IOException</span><span class="o">,</span> <span class="n">AuthenticatorException</span> <span class="o">{</span>
 <span class="n">Bundle</span> <span class="n">result</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Bundle</span><span class="o">();</span>
 <span class="n">result</span><span class="o">.</span><span class="na">putBoolean</span><span class="o">(</span><span class="n">AccountManager</span><span class="o">.</span><span class="na">KEY_BOOLEAN_RESULT</span><span class="o">,</span> <span class="n">future</span><span class="o">.</span><span class="na">getResult</span><span class="o">());</span>
 <span class="k">return</span> <span class="n">result</span><span class="o">;</span>
 <span class="o">}</span>

 <span class="nd">@Override</span>
 <span class="kd">public</span> <span class="n">Bundle</span> <span class="nf">getResult</span><span class="o">(</span><span class="kt">long</span> <span class="n">timeout</span><span class="o">,</span> <span class="n">TimeUnit</span> <span class="n">unit</span><span class="o">)</span>
 <span class="kd">throws</span> <span class="n">OperationCanceledException</span><span class="o">,</span> <span class="n">IOException</span><span class="o">,</span> <span class="n">AuthenticatorException</span> <span class="o">{</span>
 <span class="n">Bundle</span> <span class="n">result</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Bundle</span><span class="o">();</span>
 <span class="n">result</span><span class="o">.</span><span class="na">putBoolean</span><span class="o">(</span><span class="n">AccountManager</span><span class="o">.</span><span class="na">KEY_BOOLEAN_RESULT</span><span class="o">,</span> <span class="n">future</span><span class="o">.</span><span class="na">getResult</span><span class="o">(</span><span class="n">timeout</span><span class="o">,</span> <span class="n">unit</span><span class="o">));</span>
 <span class="k">return</span> <span class="n">result</span><span class="o">;</span>
 <span class="o">}</span>
 <span class="o">});</span>
 <span class="o">},</span>
 <span class="n">handler</span>
 <span class="o">);</span>
 <span class="o">}</span>
<span class="o">}</span>

Let’s do it in Kotlin

This utility method is a perfect candidate for a Kotlin extension method on AccountManager.

<span class="cm">/*
 * In API 22 (LOLLIPOP_MR1),
 * AccountManager.removeAccount(Account, Activity, AccountManagerCallback<bundle>, Handler) was added, and
 * AccountManager.removeAccount(Account, AccountManagerCallback<boolean>, Handler) was deprecated.
 *
 * To resolve this when running on a pre-22 device, call the old .removeAccount(), get the Boolean result,
 * put it in a Bundle using key AccountManager.KEY_BOOLEAN_RESULT,
 * then call AccountManagerCallback<bundle> callback.run() with a new AccountManagerFuture<bundle>
 * that returns this Bundle.
 */</bundle></bundle></boolean></bundle></span>
<span class="k">fun</span> <span class="nf">AccountManager</span><span class="p">.</span><span class="n">removeAccount</span><span class="p">(</span>
 <span class="n">account</span><span class="p">:</span> <span class="n">Account</span><span class="p">,</span>
 <span class="n">activity</span><span class="p">:</span> <span class="n">Activity</span><span class="p">?</span> <span class="p">=</span> <span class="k">null</span><span class="p">,</span>
 <span class="n">handler</span><span class="p">:</span> <span class="n">Handler</span><span class="p">?</span> <span class="p">=</span> <span class="k">null</span><span class="p">,</span>
 <span class="n">callback</span><span class="p">:</span> <span class="p">(</span><span class="n">AccountManagerFuture</span><span class="p"><</span><span class="n">Bundle</span><span class="p">>)</span> <span class="p">-></span> <span class="n">Unit</span>
<span class="p">)</span> <span class="p">{</span>
 <span class="k">if</span> <span class="p">(</span><span class="n">Build</span><span class="p">.</span><span class="n">VERSION</span><span class="p">.</span><span class="n">SDK_INT</span> <span class="p">>=</span> <span class="n">Build</span><span class="p">.</span><span class="n">VERSION_CODES</span><span class="p">.</span><span class="n">LOLLIPOP_MR1</span><span class="p">)</span> <span class="p">{</span>
 <span class="n">removeAccount</span><span class="p">(</span><span class="n">account</span><span class="p">,</span> <span class="n">activity</span><span class="p">,</span> <span class="n">callback</span><span class="p">,</span> <span class="n">handler</span><span class="p">)</span>
 <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
 <span class="n">@Suppress</span><span class="p">(</span><span class="s">"DEPRECATION"</span><span class="p">)</span>
 <span class="n">removeAccount</span><span class="p">(</span>
 <span class="n">account</span><span class="p">,</span>
 <span class="p">{</span> <span class="n">future</span> <span class="p">-></span>
 <span class="n">callback</span><span class="p">(</span><span class="kd">object</span> <span class="err">: </span><span class="nc">AccountManagerFuture</span><span class="p"><</span><span class="n">Bundle</span><span class="p">></span> <span class="p">{</span>
 <span class="k">override</span> <span class="k">fun</span> <span class="nf">cancel</span><span class="p">(</span><span class="n">mayInterruptIfRunning</span><span class="p">:</span> <span class="n">Boolean</span><span class="p">):</span> <span class="n">Boolean</span> <span class="p">{</span>
 <span class="k">return</span> <span class="n">future</span><span class="p">.</span><span class="n">cancel</span><span class="p">(</span><span class="n">mayInterruptIfRunning</span><span class="p">)</span>
 <span class="p">}</span>

 <span class="k">override</span> <span class="k">fun</span> <span class="nf">isCancelled</span><span class="p">():</span> <span class="n">Boolean</span> <span class="p">{</span>
 <span class="k">return</span> <span class="n">future</span><span class="p">.</span><span class="n">isCancelled</span>
 <span class="p">}</span>

 <span class="k">override</span> <span class="k">fun</span> <span class="nf">isDone</span><span class="p">():</span> <span class="n">Boolean</span> <span class="p">{</span>
 <span class="k">return</span> <span class="n">future</span><span class="p">.</span><span class="n">isDone</span>
 <span class="p">}</span>

 <span class="k">override</span> <span class="k">fun</span> <span class="nf">getResult</span><span class="p">():</span> <span class="n">Bundle</span> <span class="p">{</span>
 <span class="kd">val</span> <span class="py">bundle</span> <span class="p">=</span> <span class="n">Bundle</span><span class="p">()</span>
 <span class="n">bundle</span><span class="p">.</span><span class="n">putBoolean</span><span class="p">(</span><span class="n">AccountManager</span><span class="p">.</span><span class="n">KEY_BOOLEAN_RESULT</span><span class="p">,</span> <span class="n">future</span><span class="p">.</span><span class="n">getResult</span><span class="p">())</span>
 <span class="k">return</span> <span class="n">bundle</span>
 <span class="p">}</span>

 <span class="k">override</span> <span class="k">fun</span> <span class="nf">getResult</span><span class="p">(</span><span class="n">timeout</span><span class="p">:</span> <span class="n">Long</span><span class="p">,</span> <span class="n">unit</span><span class="p">:</span> <span class="n">TimeUnit</span><span class="p">):</span> <span class="n">Bundle</span> <span class="p">{</span>
 <span class="kd">val</span> <span class="py">bundle</span> <span class="p">=</span> <span class="n">Bundle</span><span class="p">()</span>
 <span class="n">bundle</span><span class="p">.</span><span class="n">putBoolean</span><span class="p">(</span><span class="n">AccountManager</span><span class="p">.</span><span class="n">KEY_BOOLEAN_RESULT</span><span class="p">,</span> <span class="n">future</span><span class="p">.</span><span class="n">getResult</span><span class="p">(</span><span class="n">timeout</span><span class="p">,</span> <span class="n">unit</span><span class="p">))</span>
 <span class="k">return</span> <span class="n">bundle</span>
 <span class="p">}</span>
 <span class="p">})</span>
 <span class="p">},</span>
 <span class="n">handler</span>
 <span class="p">)</span>
 <span class="p">}</span>
<span class="p">}</span>

You can find this code in this Github gist. The Kotlin version is courtesy of my co-workers Josh Friend and Scott Schmitz.

Ready to get started?

Call us at 616-594-0269 or send us a note below.
Visit our office @ 452 Ada Drive SE Suite 300 Ada, Michigan 49301
Send us an e-mail @ info@michiganlabs.com