From b4df28ae3b55ab70f4851244d23940ff21c21531 Mon Sep 17 00:00:00 2001 From: Alex Baker Date: Tue, 10 Nov 2020 15:50:27 -0600 Subject: [PATCH] Convert GoogleAccountManager to Kotlin --- .../astrid/gtasks/auth/GtasksLoginActivity.kt | 2 +- .../org/tasks/drive/DriveLoginActivity.java | 2 +- .../tasks/gtasks/GoogleAccountManager.java | 140 ------------------ .../org/tasks/gtasks/GoogleAccountManager.kt | 123 +++++++++++++++ 4 files changed, 125 insertions(+), 142 deletions(-) delete mode 100644 app/src/main/java/org/tasks/gtasks/GoogleAccountManager.java create mode 100644 app/src/main/java/org/tasks/gtasks/GoogleAccountManager.kt diff --git a/app/src/main/java/com/todoroo/astrid/gtasks/auth/GtasksLoginActivity.kt b/app/src/main/java/com/todoroo/astrid/gtasks/auth/GtasksLoginActivity.kt index 45488d8b5..b2b0c1e87 100644 --- a/app/src/main/java/com/todoroo/astrid/gtasks/auth/GtasksLoginActivity.kt +++ b/app/src/main/java/com/todoroo/astrid/gtasks/auth/GtasksLoginActivity.kt @@ -53,7 +53,7 @@ class GtasksLoginActivity : InjectingAppCompatActivity() { private fun chooseAccount() { val chooseAccountIntent = AccountManager.newChooseAccountIntent( - null, null, arrayOf("com.google"), false, null, null, null, null) + null, null, arrayOf("com.google"), null, null, null, null) startActivityForResult(chooseAccountIntent, RC_CHOOSE_ACCOUNT) } diff --git a/app/src/main/java/org/tasks/drive/DriveLoginActivity.java b/app/src/main/java/org/tasks/drive/DriveLoginActivity.java index 0cd71a275..5b5a9beab 100644 --- a/app/src/main/java/org/tasks/drive/DriveLoginActivity.java +++ b/app/src/main/java/org/tasks/drive/DriveLoginActivity.java @@ -40,7 +40,7 @@ public class DriveLoginActivity extends InjectingAppCompatActivity { Intent chooseAccountIntent = android.accounts.AccountManager.newChooseAccountIntent( - null, null, new String[] {"com.google"}, false, null, null, null, null); + null, null, new String[] {"com.google"}, null, null, null, null); startActivityForResult(chooseAccountIntent, RC_CHOOSE_ACCOUNT); } diff --git a/app/src/main/java/org/tasks/gtasks/GoogleAccountManager.java b/app/src/main/java/org/tasks/gtasks/GoogleAccountManager.java deleted file mode 100644 index 64fae7aee..000000000 --- a/app/src/main/java/org/tasks/gtasks/GoogleAccountManager.java +++ /dev/null @@ -1,140 +0,0 @@ -package org.tasks.gtasks; - -import static com.google.common.collect.Iterables.tryFind; -import static com.google.common.collect.Lists.transform; -import static com.todoroo.andlib.utility.AndroidUtilities.assertNotMainThread; -import static java.util.Arrays.asList; -import static org.tasks.Strings.isNullOrEmpty; - -import android.accounts.Account; -import android.accounts.AccountManager; -import android.accounts.AuthenticatorException; -import android.accounts.OperationCanceledException; -import android.annotation.SuppressLint; -import android.app.Activity; -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import com.google.api.services.drive.DriveScopes; -import com.google.api.services.tasks.TasksScopes; -import dagger.hilt.android.qualifiers.ApplicationContext; -import io.reactivex.Single; -import io.reactivex.android.schedulers.AndroidSchedulers; -import io.reactivex.schedulers.Schedulers; -import java.io.IOException; -import java.util.Collections; -import java.util.List; -import javax.inject.Inject; -import org.tasks.R; -import org.tasks.play.AuthResultHandler; -import org.tasks.preferences.PermissionChecker; -import org.tasks.preferences.Preferences; -import timber.log.Timber; - -public class GoogleAccountManager { - - private final PermissionChecker permissionChecker; - private final android.accounts.AccountManager accountManager; - private final Preferences preferences; - - @Inject - public GoogleAccountManager( - @ApplicationContext Context context, PermissionChecker permissionChecker, Preferences preferences) { - this.permissionChecker = permissionChecker; - accountManager = android.accounts.AccountManager.get(context); - this.preferences = preferences; - } - - public List getAccounts() { - return transform(getAccountList(), account -> account.name); - } - - private List getAccountList() { - return permissionChecker.canAccessAccounts() - ? asList(accountManager.getAccountsByType("com.google")) - : Collections.emptyList(); - } - - public Account getAccount(String name) { - if (isNullOrEmpty(name)) { - return null; - } - - return tryFind(getAccountList(), account -> name.equalsIgnoreCase(account.name)).orNull(); - } - - public boolean canAccessAccount(String name) { - return getAccount(name) != null; - } - - public String getAccessToken(String name, String scope) { - assertNotMainThread(); - - Account account = getAccount(name); - if (account == null) { - Timber.e("Cannot find account %s", name); - return null; - } - - boolean alreadyNotified = preferences.alreadyNotified(name, scope); - - try { - String token = - accountManager.blockingGetAuthToken(account, "oauth2:" + scope, !alreadyNotified); - preferences.setAlreadyNotified(name, scope, isNullOrEmpty(token)); - return token; - } catch (AuthenticatorException | IOException | OperationCanceledException e) { - Timber.e(e); - return null; - } - } - - public void getTasksAuthToken( - final Activity activity, final String accountName, final AuthResultHandler handler) { - getToken(TasksScopes.TASKS, activity, accountName, handler); - } - - public void getDriveAuthToken( - final Activity activity, final String accountName, final AuthResultHandler handler) { - getToken(DriveScopes.DRIVE_FILE, activity, accountName, handler); - } - - @SuppressWarnings("ResultOfMethodCallIgnored") - @SuppressLint("CheckResult") - private void getToken( - String scope, Activity activity, String accountName, AuthResultHandler handler) { - final Account account = getAccount(accountName); - Single.fromCallable( - () -> { - if (account == null) { - throw new RuntimeException( - activity.getString(R.string.gtasks_error_accountNotFound, accountName)); - } - assertNotMainThread(); - - return accountManager - .getAuthToken(account, "oauth2:" + scope, new Bundle(), activity, null, null) - .getResult(); - }) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe( - bundle -> { - preferences.setAlreadyNotified(accountName, scope, false); - Intent intent = (Intent) bundle.get(AccountManager.KEY_INTENT); - if (intent != null) { - activity.startActivity(intent); - } else { - handler.authenticationSuccessful(accountName); - } - }, - e -> { - Timber.e(e); - handler.authenticationFailed(e.getMessage()); - }); - } - - public void invalidateToken(String token) { - accountManager.invalidateAuthToken("com.google", token); - } -} diff --git a/app/src/main/java/org/tasks/gtasks/GoogleAccountManager.kt b/app/src/main/java/org/tasks/gtasks/GoogleAccountManager.kt new file mode 100644 index 000000000..a809095a7 --- /dev/null +++ b/app/src/main/java/org/tasks/gtasks/GoogleAccountManager.kt @@ -0,0 +1,123 @@ +package org.tasks.gtasks + +import android.accounts.Account +import android.accounts.AccountManager +import android.accounts.AuthenticatorException +import android.accounts.OperationCanceledException +import android.annotation.SuppressLint +import android.app.Activity +import android.content.Context +import android.content.Intent +import android.os.Bundle +import com.google.api.services.drive.DriveScopes +import com.google.api.services.tasks.TasksScopes +import com.google.common.collect.Lists +import com.todoroo.andlib.utility.AndroidUtilities +import dagger.hilt.android.qualifiers.ApplicationContext +import io.reactivex.Single +import io.reactivex.android.schedulers.AndroidSchedulers +import io.reactivex.schedulers.Schedulers +import org.tasks.R +import org.tasks.Strings.isNullOrEmpty +import org.tasks.play.AuthResultHandler +import org.tasks.preferences.PermissionChecker +import org.tasks.preferences.Preferences +import timber.log.Timber +import java.io.IOException +import javax.inject.Inject + +class GoogleAccountManager @Inject constructor( + @ApplicationContext context: Context?, + private val permissionChecker: PermissionChecker, + private val preferences: Preferences +) { + private val accountManager: AccountManager = AccountManager.get(context) + + val accounts: List + get() = Lists.transform(accountList) { account: Account? -> account!!.name } + + private val accountList: List + get() = if (permissionChecker.canAccessAccounts()) { + accountManager.getAccountsByType("com.google").toList() + } else { + emptyList() + } + + fun getAccount(name: String): Account? = if (isNullOrEmpty(name)) { + null + } else { + accountList.find { name.equals(it.name, ignoreCase = true) } + } + + fun canAccessAccount(name: String): Boolean { + return getAccount(name) != null + } + + fun getAccessToken(name: String, scope: String): String? { + AndroidUtilities.assertNotMainThread() + val account = getAccount(name) + if (account == null) { + Timber.e("Cannot find account %s", name) + return null + } + val alreadyNotified = preferences.alreadyNotified(name, scope) + return try { + val token = accountManager.blockingGetAuthToken(account, "oauth2:$scope", !alreadyNotified) + preferences.setAlreadyNotified(name, scope, isNullOrEmpty(token)) + token + } catch (e: AuthenticatorException) { + Timber.e(e) + null + } catch (e: IOException) { + Timber.e(e) + null + } catch (e: OperationCanceledException) { + Timber.e(e) + null + } + } + + fun getTasksAuthToken(activity: Activity, accountName: String, handler: AuthResultHandler) { + getToken(TasksScopes.TASKS, activity, accountName, handler) + } + + fun getDriveAuthToken(activity: Activity, accountName: String, handler: AuthResultHandler) { + getToken(DriveScopes.DRIVE_FILE, activity, accountName, handler) + } + + @SuppressLint("CheckResult") + private fun getToken( + scope: String, activity: Activity, accountName: String, handler: AuthResultHandler) { + val account = getAccount(accountName) + Single.fromCallable { + if (account == null) { + throw RuntimeException( + activity.getString(R.string.gtasks_error_accountNotFound, accountName)) + } + AndroidUtilities.assertNotMainThread() + accountManager + .getAuthToken(account, "oauth2:$scope", Bundle(), activity, null, null) + .result + } + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe( + { bundle: Bundle -> + preferences.setAlreadyNotified(accountName, scope, false) + val intent = bundle[AccountManager.KEY_INTENT] as Intent? + if (intent != null) { + activity.startActivity(intent) + } else { + handler.authenticationSuccessful(accountName) + } + } + ) { e: Throwable -> + Timber.e(e) + handler.authenticationFailed(e.message) + } + } + + fun invalidateToken(token: String?) { + accountManager.invalidateAuthToken("com.google", token) + } +} \ No newline at end of file