Last active
May 12, 2020 09:03
-
-
Save iffa/07fbf982d13a585b3c728123cb282f4a to your computer and use it in GitHub Desktop.
AccountManager wrapper with an easier API and RxJava support
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Wrapper for {@link AccountManager} with improved functionality and RxJava support. | |
* | |
* Originally found from <a href="https://github.com/novoda/spikes/tree/master/gertherb/android/src/main/java/com/gertherb/authentication">github.com/spikes/gertherb</a>, | |
* and modified to work with a newer RxJava version, using {@link Single} instead of {@link rx.Observable}. | |
* | |
* @author Ataul Munim | |
* @author Santeri Elo | |
*/ | |
public class BetterAccountManager { | |
private final AccountManager accountManager; | |
private final Activity activity; | |
@Inject public BetterAccountManager(Activity activity) { | |
this.activity = activity; | |
this.accountManager = AccountManager.get(activity.getApplicationContext()); | |
} | |
/** | |
* Starts the login flow and gets the new user's access token. | |
* | |
* @param options {@link Bundle} may be empty or null (not that important) | |
* @return Single emitting a {@link Token} | |
*/ | |
public Single<Token> addAccountAndGetToken(final Bundle options) { | |
return addAccount(options) | |
.flatMap(s -> getSessionKey(options)) | |
.compose(applySchedulers()); | |
} | |
/** | |
* Gets the current user's access token. If no user is logged in, normal login flow is started. | |
* | |
* @param options {@link Bundle} may be empty or null (not that important) | |
* @return Single emitting a {@link Token} | |
*/ | |
public Single<Token> getSessionKeyOrAddAccount(Bundle options) { | |
return getSessionKey(options) | |
.onErrorResumeNext(addNewAccount(options)) | |
.compose(applySchedulers()); | |
} | |
private Single<Token> getSessionKey(final Bundle options) { | |
return Single.create(new Single.OnSubscribe<Token>() { | |
@Override | |
public void call(SingleSubscriber<? super Token> subscriber) { | |
Account[] accounts = accountManager.getAccountsByType(ACCOUNT_TYPE); | |
if (accounts.length == 0) { | |
subscriber.onError(new NoAccountException()); | |
return; | |
} | |
Bundle result; | |
try { | |
result = getAuthToken(accounts[0], options); | |
} catch (AuthenticatorException | OperationCanceledException | IOException e) { | |
subscriber.onError(e); | |
return; | |
} | |
subscriber.onSuccess(new Token(accounts[0].name, result.getString(AccountManager.KEY_AUTHTOKEN))); | |
} | |
}); | |
} | |
private Bundle getAuthToken(Account account, Bundle options) throws AuthenticatorException, OperationCanceledException, IOException { | |
return accountManager.getAuthToken(account, AUTHTOKEN_TYPE, options, activity, null, null).getResult(); | |
} | |
private Func1<Throwable, Single<? extends Token>> addNewAccount(final Bundle options) { | |
return onErrorThrowable -> { | |
if (onErrorThrowable.getCause() instanceof NoAccountException) { | |
return addAccountAndGetToken(options); | |
} | |
return Single.error(onErrorThrowable.getCause()); | |
}; | |
} | |
private Single<String> addAccount(final Bundle options) { | |
return Single.create(new Single.OnSubscribe<String>() { | |
@Override | |
public void call(SingleSubscriber<? super String> subscriber) { | |
Bundle result; | |
try { | |
result = accountManager.addAccount(ACCOUNT_TYPE, AUTHTOKEN_TYPE, null, options, activity, null, null).getResult(); | |
} catch (OperationCanceledException | AuthenticatorException | IOException e) { | |
subscriber.onError(e); | |
return; | |
} | |
subscriber.onSuccess(result.getString(AccountManager.KEY_ACCOUNT_NAME)); | |
} | |
}); | |
} | |
private <T> Single.Transformer<T, T> applySchedulers() { | |
return observable -> observable.subscribeOn(Schedulers.io()) | |
.observeOn(AndroidSchedulers.mainThread()); | |
} | |
} |
This gist is for RxJava v1?
Yes, but I don't see why this couldn't be adapted for RxJava2+ with small changes.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This gist is for RxJava v1?