diff --git a/app/src/main/java/com/todoroo/astrid/gtasks/api/HttpCredentialsAdapter.kt b/app/src/main/java/com/todoroo/astrid/gtasks/api/HttpCredentialsAdapter.kt index 2856bf241..da4f3e295 100644 --- a/app/src/main/java/com/todoroo/astrid/gtasks/api/HttpCredentialsAdapter.kt +++ b/app/src/main/java/com/todoroo/astrid/gtasks/api/HttpCredentialsAdapter.kt @@ -62,7 +62,7 @@ class HttpCredentialsAdapter @Inject constructor(private val googleAccountManage } } - fun checkToken(account: String?, scope: String) { + suspend fun checkToken(account: String?, scope: String) { if (credentials == null) { val token = googleAccountManager.getAccessToken(account, scope) credentials = GoogleCredentials(AccessToken(token, null)) 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 b2b0c1e87..fe3e74d48 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 @@ -25,7 +25,6 @@ import org.tasks.data.GoogleTaskListDao import org.tasks.dialogs.DialogBuilder import org.tasks.gtasks.GoogleAccountManager import org.tasks.injection.InjectingAppCompatActivity -import org.tasks.play.AuthResultHandler import org.tasks.preferences.ActivityPermissionRequestor import org.tasks.preferences.PermissionRequestor import javax.inject.Inject @@ -57,19 +56,20 @@ class GtasksLoginActivity : InjectingAppCompatActivity() { startActivityForResult(chooseAccountIntent, RC_CHOOSE_ACCOUNT) } - private fun getAuthToken(account: String) { + private suspend fun getAuthToken(account: String) { val pd = dialogBuilder.newProgressDialog(R.string.gtasks_GLA_authenticating) pd.show() getAuthToken(account, pd) } - private fun getAuthToken(a: String, pd: ProgressDialog) { - googleAccountManager.getTasksAuthToken( - this, - a, - object : AuthResultHandler { - override fun authenticationSuccessful(accountName: String) { - lifecycleScope.launch { + private suspend fun getAuthToken(accountName: String, pd: ProgressDialog) { + try { + googleAccountManager.getTasksAuthToken(this, accountName) + ?.let { bundle -> + val intent = bundle[AccountManager.KEY_INTENT] + if (intent is Intent) { + startActivity(intent) + } else { withContext(NonCancellable) { var account = googleTaskListDao.getAccount(accountName) if (account == null) { @@ -92,19 +92,20 @@ class GtasksLoginActivity : InjectingAppCompatActivity() { } } - override fun authenticationFailed(message: String?) { - setResult(Activity.RESULT_CANCELED, Intent().putExtra(EXTRA_ERROR, message)) - DialogUtilities.dismissDialog(this@GtasksLoginActivity, pd) - finish() - } - }) + } catch (e: Exception) { + setResult(Activity.RESULT_CANCELED, Intent().putExtra(EXTRA_ERROR, e.message)) + DialogUtilities.dismissDialog(this@GtasksLoginActivity, pd) + finish() + } } override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { if (requestCode == RC_CHOOSE_ACCOUNT) { if (resultCode == Activity.RESULT_OK) { val account = data!!.getStringExtra(AccountManager.KEY_ACCOUNT_NAME)!! - getAuthToken(account) + lifecycleScope.launch { + getAuthToken(account) + } } else { finish() } diff --git a/app/src/main/java/org/tasks/drive/DriveLoginActivity.java b/app/src/main/java/org/tasks/drive/DriveLoginActivity.java deleted file mode 100644 index 5b5a9beab..000000000 --- a/app/src/main/java/org/tasks/drive/DriveLoginActivity.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2012 Todoroo Inc - * - * See the file "LICENSE" for the full license governing this code. - */ - -package org.tasks.drive; - -import android.app.ProgressDialog; -import android.content.Intent; -import android.os.Bundle; -import com.todoroo.andlib.utility.DialogUtilities; -import dagger.hilt.android.AndroidEntryPoint; -import javax.inject.Inject; -import org.tasks.R; -import org.tasks.dialogs.DialogBuilder; -import org.tasks.gtasks.GoogleAccountManager; -import org.tasks.injection.InjectingAppCompatActivity; -import org.tasks.play.AuthResultHandler; -import org.tasks.preferences.Preferences; - -/** - * This activity allows users to sign in or log in to Google Tasks through the Android account - * manager - * - * @author Sam Bosley - */ -@AndroidEntryPoint -public class DriveLoginActivity extends InjectingAppCompatActivity { - - public static final String EXTRA_ERROR = "extra_error"; - private static final int RC_CHOOSE_ACCOUNT = 10988; - @Inject DialogBuilder dialogBuilder; - @Inject GoogleAccountManager googleAccountManager; - @Inject Preferences preferences; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - Intent chooseAccountIntent = - android.accounts.AccountManager.newChooseAccountIntent( - null, null, new String[] {"com.google"}, null, null, null, null); - startActivityForResult(chooseAccountIntent, RC_CHOOSE_ACCOUNT); - } - - private void getAuthToken(String account) { - final ProgressDialog pd = dialogBuilder.newProgressDialog(R.string.gtasks_GLA_authenticating); - pd.show(); - getAuthToken(account, pd); - } - - private void getAuthToken(String a, final ProgressDialog pd) { - googleAccountManager.getDriveAuthToken( - this, - a, - new AuthResultHandler() { - @Override - public void authenticationSuccessful(String accountName) { - preferences.setString(R.string.p_google_drive_backup_account, accountName); - preferences.setBoolean(R.string.p_google_drive_backup, true); - setResult(RESULT_OK); - DialogUtilities.dismissDialog(DriveLoginActivity.this, pd); - finish(); - } - - @Override - public void authenticationFailed(final String message) { - preferences.setBoolean(R.string.p_google_drive_backup, false); - setResult(RESULT_CANCELED, new Intent().putExtra(EXTRA_ERROR, message)); - DialogUtilities.dismissDialog(DriveLoginActivity.this, pd); - finish(); - } - }); - } - - @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) { - if (requestCode == RC_CHOOSE_ACCOUNT) { - if (resultCode == RESULT_OK) { - String account = data.getStringExtra(android.accounts.AccountManager.KEY_ACCOUNT_NAME); - getAuthToken(account); - } else { - finish(); - } - } else { - super.onActivityResult(requestCode, resultCode, data); - } - } -} diff --git a/app/src/main/java/org/tasks/drive/DriveLoginActivity.kt b/app/src/main/java/org/tasks/drive/DriveLoginActivity.kt new file mode 100644 index 000000000..8e60d5cad --- /dev/null +++ b/app/src/main/java/org/tasks/drive/DriveLoginActivity.kt @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2012 Todoroo Inc + * + * See the file "LICENSE" for the full license governing this code. + */ +package org.tasks.drive + +import android.accounts.AccountManager +import android.app.ProgressDialog +import android.content.Intent +import android.os.Bundle +import androidx.lifecycle.lifecycleScope +import com.todoroo.andlib.utility.DialogUtilities +import dagger.hilt.android.AndroidEntryPoint +import kotlinx.coroutines.launch +import org.tasks.R +import org.tasks.dialogs.DialogBuilder +import org.tasks.gtasks.GoogleAccountManager +import org.tasks.injection.InjectingAppCompatActivity +import org.tasks.preferences.Preferences +import javax.inject.Inject + +/** + * This activity allows users to sign in or log in to Google Tasks through the Android account + * manager + * + * @author Sam Bosley + */ +@AndroidEntryPoint +class DriveLoginActivity : InjectingAppCompatActivity() { + @Inject lateinit var dialogBuilder: DialogBuilder + @Inject lateinit var googleAccountManager: GoogleAccountManager + @Inject lateinit var preferences: Preferences + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + val chooseAccountIntent = AccountManager.newChooseAccountIntent( + null, null, arrayOf("com.google"), null, null, null, null) + startActivityForResult(chooseAccountIntent, RC_CHOOSE_ACCOUNT) + } + + private suspend fun getAuthToken(account: String?) { + val pd = dialogBuilder.newProgressDialog(R.string.gtasks_GLA_authenticating) + pd.show() + getAuthToken(account, pd) + } + + private suspend fun getAuthToken(accountName: String?, pd: ProgressDialog) { + try { + googleAccountManager.getDriveAuthToken(this, accountName!!) + ?.let { bundle -> + val intent = bundle[AccountManager.KEY_INTENT] + if (intent is Intent) { + startActivity(intent) + } else { + preferences.setString(R.string.p_google_drive_backup_account, accountName) + preferences.setBoolean(R.string.p_google_drive_backup, true) + setResult(RESULT_OK) + DialogUtilities.dismissDialog(this@DriveLoginActivity, pd) + finish() + } + } + } catch (e: Exception) { + preferences.setBoolean(R.string.p_google_drive_backup, false) + setResult(RESULT_CANCELED, Intent().putExtra(EXTRA_ERROR, e.message)) + DialogUtilities.dismissDialog(this@DriveLoginActivity, pd) + finish() + } + } + + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + if (requestCode == RC_CHOOSE_ACCOUNT) { + if (resultCode == RESULT_OK) { + val account = data!!.getStringExtra(AccountManager.KEY_ACCOUNT_NAME) + lifecycleScope.launch { + getAuthToken(account) + } + } else { + finish() + } + } else { + super.onActivityResult(requestCode, resultCode, data) + } + } + + companion object { + const val EXTRA_ERROR = "extra_error" + private const val RC_CHOOSE_ACCOUNT = 10988 + } +} \ No newline at end of file diff --git a/app/src/main/java/org/tasks/gtasks/GoogleAccountManager.kt b/app/src/main/java/org/tasks/gtasks/GoogleAccountManager.kt index a809095a7..79d150fe8 100644 --- a/app/src/main/java/org/tasks/gtasks/GoogleAccountManager.kt +++ b/app/src/main/java/org/tasks/gtasks/GoogleAccountManager.kt @@ -7,19 +7,15 @@ 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 kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext 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 @@ -43,7 +39,7 @@ class GoogleAccountManager @Inject constructor( emptyList() } - fun getAccount(name: String): Account? = if (isNullOrEmpty(name)) { + fun getAccount(name: String?): Account? = if (isNullOrEmpty(name)) { null } else { accountList.find { name.equals(it.name, ignoreCase = true) } @@ -53,16 +49,17 @@ class GoogleAccountManager @Inject constructor( return getAccount(name) != null } - fun getAccessToken(name: String, scope: String): String? { - AndroidUtilities.assertNotMainThread() - val account = getAccount(name) + suspend fun getAccessToken(name: String?, scope: String): String? { + val account = name?.let { getAccount(it) } 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) + val token = withContext(Dispatchers.IO) { + accountManager.blockingGetAuthToken(account, "oauth2:$scope", !alreadyNotified) + } preferences.setAlreadyNotified(name, scope, isNullOrEmpty(token)) token } catch (e: AuthenticatorException) { @@ -77,44 +74,26 @@ class GoogleAccountManager @Inject constructor( } } - fun getTasksAuthToken(activity: Activity, accountName: String, handler: AuthResultHandler) { - getToken(TasksScopes.TASKS, activity, accountName, handler) + suspend fun getTasksAuthToken(activity: Activity, accountName: String): Bundle? { + return getToken(TasksScopes.TASKS, activity, accountName) } - fun getDriveAuthToken(activity: Activity, accountName: String, handler: AuthResultHandler) { - getToken(DriveScopes.DRIVE_FILE, activity, accountName, handler) + suspend fun getDriveAuthToken(activity: Activity, accountName: String): Bundle? { + return getToken(DriveScopes.DRIVE_FILE, activity, accountName) } @SuppressLint("CheckResult") - private fun getToken( - scope: String, activity: Activity, accountName: String, handler: AuthResultHandler) { + private suspend fun getToken(scope: String, activity: Activity, accountName: String): Bundle? { val account = getAccount(accountName) - Single.fromCallable { - if (account == null) { - throw RuntimeException( + ?: throw RuntimeException( activity.getString(R.string.gtasks_error_accountNotFound, accountName)) - } - AndroidUtilities.assertNotMainThread() - accountManager + return withContext(Dispatchers.IO) { + val bundle = accountManager .getAuthToken(account, "oauth2:$scope", Bundle(), activity, null, null) .result + preferences.setAlreadyNotified(accountName, scope, false) + bundle } - .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?) { diff --git a/app/src/main/java/org/tasks/play/AuthResultHandler.kt b/app/src/main/java/org/tasks/play/AuthResultHandler.kt deleted file mode 100644 index 97d453633..000000000 --- a/app/src/main/java/org/tasks/play/AuthResultHandler.kt +++ /dev/null @@ -1,7 +0,0 @@ -package org.tasks.play - -interface AuthResultHandler { - fun authenticationSuccessful(accountName: String) - - fun authenticationFailed(message: String?) -} \ No newline at end of file