Merge pull request #851 from akaita/rx_authentication

Rx for Auth tasks
This commit is contained in:
Yusuke Matsubara 2017-08-24 23:15:59 +09:00 committed by GitHub
commit 0c680b06ca

View file

@ -3,15 +3,13 @@ package fr.free.nrw.commons.auth;
import android.accounts.Account; import android.accounts.Account;
import android.accounts.AccountManager; import android.accounts.AccountManager;
import android.accounts.AccountManagerFuture; import android.accounts.AccountManagerFuture;
import android.accounts.AuthenticatorException;
import android.accounts.OperationCanceledException;
import android.os.AsyncTask;
import android.os.Bundle; import android.os.Bundle;
import java.io.IOException;
import fr.free.nrw.commons.CommonsApplication; import fr.free.nrw.commons.CommonsApplication;
import fr.free.nrw.commons.theme.NavigationBaseActivity; import fr.free.nrw.commons.theme.NavigationBaseActivity;
import io.reactivex.Single;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
import timber.log.Timber; import timber.log.Timber;
public abstract class AuthenticatedActivity extends NavigationBaseActivity { public abstract class AuthenticatedActivity extends NavigationBaseActivity {
@ -24,87 +22,36 @@ public abstract class AuthenticatedActivity extends NavigationBaseActivity {
public AuthenticatedActivity() { public AuthenticatedActivity() {
this.accountType = AccountUtil.accountType(); this.accountType = AccountUtil.accountType();
} }
private class GetAuthCookieTask extends AsyncTask<Void, String, String> {
private Account account;
private AccountManager accountManager;
public GetAuthCookieTask(Account account, AccountManager accountManager) {
this.account = account;
this.accountManager = accountManager;
}
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
if(result != null) {
authCookie = result;
onAuthCookieAcquired(result);
} else {
onAuthFailure();
}
}
@Override private void getAuthCookie(Account account, AccountManager accountManager) {
protected String doInBackground(Void... params) { Single.fromCallable(() -> accountManager.blockingGetAuthToken(account, "", false))
try { .subscribeOn(Schedulers.io())
return accountManager.blockingGetAuthToken(account, "", false); .doOnError(Timber::e)
} catch (OperationCanceledException e) { .observeOn(AndroidSchedulers.mainThread())
e.printStackTrace(); .subscribe(
return null; cookie -> onAuthCookieAcquired(cookie),
} catch (AuthenticatorException e) { throwable -> onAuthFailure());
e.printStackTrace();
return null;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
} }
private class AddAccountTask extends AsyncTask<Void, String, String> {
private AccountManager accountManager;
public AddAccountTask(AccountManager accountManager) {
this.accountManager = accountManager;
}
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
if(result != null) {
Account[] allAccounts =accountManager.getAccountsByType(accountType);
Account curAccount = allAccounts[0];
GetAuthCookieTask getCookieTask = new GetAuthCookieTask(curAccount, accountManager);
getCookieTask.execute();
} else {
onAuthFailure();
}
}
@Override private void addAccount(AccountManager accountManager) {
protected String doInBackground(Void... params) { Single.just(accountManager.addAccount(accountType, null, null, null, AuthenticatedActivity.this, null, null))
AccountManagerFuture<Bundle> resultFuture = accountManager.addAccount(accountType, null, null, null, AuthenticatedActivity.this, null, null); .subscribeOn(Schedulers.io())
Bundle result; .map(AccountManagerFuture::getResult)
try { .doOnEvent((bundle, throwable) -> {
result = resultFuture.getResult(); if (!bundle.containsKey(AccountManager.KEY_ACCOUNT_NAME)) {
} catch (OperationCanceledException e) { throw new RuntimeException("Bundle doesn't contain account-name key: "
e.printStackTrace(); + AccountManager.KEY_ACCOUNT_NAME);
return null; }
} catch (AuthenticatorException e) { })
// TODO Auto-generated catch block .map(bundle -> bundle.getString(AccountManager.KEY_ACCOUNT_NAME))
e.printStackTrace(); .doOnError(Timber::e)
return null; .observeOn(AndroidSchedulers.mainThread())
} catch (IOException e) { .subscribe(s -> {
// TODO Auto-generated catch block Account[] allAccounts = accountManager.getAccountsByType(accountType);
e.printStackTrace(); Account curAccount = allAccounts[0];
return null; getAuthCookie(curAccount, accountManager);
} },
if(result.containsKey(AccountManager.KEY_ACCOUNT_NAME)) { throwable -> onAuthFailure());
return result.getString(AccountManager.KEY_ACCOUNT_NAME);
} else {
return null;
}
}
} }
protected void requestAuthToken() { protected void requestAuthToken() {
@ -115,17 +62,9 @@ public abstract class AuthenticatedActivity extends NavigationBaseActivity {
AccountManager accountManager = AccountManager.get(this); AccountManager accountManager = AccountManager.get(this);
Account curAccount = app.getCurrentAccount(); Account curAccount = app.getCurrentAccount();
if(curAccount == null) { if(curAccount == null) {
AddAccountTask addAccountTask = new AddAccountTask(accountManager); addAccount(accountManager);
// This AsyncTask blocks until the Login Activity returns
// And since in Android 4.x+ only one background thread runs all AsyncTasks
// And since LoginActivity can't return until it's own AsyncTask (that does the login)
// returns, we have a deadlock!
// Fixed by explicitly asking this to be executed in parallel
// See: https://groups.google.com/forum/?fromgroups=#!topic/android-developers/8M0RTFfO7-M
addAccountTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
} else { } else {
GetAuthCookieTask task = new GetAuthCookieTask(curAccount, accountManager); getAuthCookie(curAccount, accountManager);
task.execute();
} }
} }