diff --git a/app/src/main/java/com/todoroo/astrid/gtasks/api/GtasksInvoker.java b/app/src/main/java/com/todoroo/astrid/gtasks/api/GtasksInvoker.java index b8e6ae931..ad77bd9ed 100644 --- a/app/src/main/java/com/todoroo/astrid/gtasks/api/GtasksInvoker.java +++ b/app/src/main/java/com/todoroo/astrid/gtasks/api/GtasksInvoker.java @@ -1,8 +1,6 @@ package com.todoroo.astrid.gtasks.api; -import android.accounts.AccountManager; import android.content.Context; -import android.os.Bundle; import androidx.annotation.Nullable; import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; import com.google.api.client.http.HttpRequest; @@ -82,9 +80,7 @@ public class GtasksInvoker { private void checkToken() { if (credential != null && Strings.isNullOrEmpty(credential.getAccessToken())) { - Bundle bundle = googleAccountManager.getAccessToken(account, TasksScopes.TASKS); - credential.setAccessToken( - bundle != null ? bundle.getString(AccountManager.KEY_AUTHTOKEN) : null); + credential.setAccessToken(googleAccountManager.getAccessToken(account, TasksScopes.TASKS)); } } diff --git a/app/src/main/java/org/tasks/drive/DriveInvoker.java b/app/src/main/java/org/tasks/drive/DriveInvoker.java index 965de5322..53a6c0181 100644 --- a/app/src/main/java/org/tasks/drive/DriveInvoker.java +++ b/app/src/main/java/org/tasks/drive/DriveInvoker.java @@ -2,10 +2,8 @@ package org.tasks.drive; import static com.todoroo.andlib.utility.DateUtilities.now; -import android.accounts.AccountManager; import android.content.Context; import android.net.Uri; -import android.os.Bundle; import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; import com.google.api.client.http.HttpResponse; import com.google.api.client.http.HttpResponseException; @@ -61,9 +59,8 @@ public class DriveInvoker { private void checkToken() { if (Strings.isNullOrEmpty(credential.getAccessToken())) { String account = preferences.getStringValue(R.string.p_google_drive_backup_account); - Bundle bundle = googleAccountManager.getAccessToken(account, DriveScopes.DRIVE_FILE); credential.setAccessToken( - bundle != null ? bundle.getString(AccountManager.KEY_AUTHTOKEN) : null); + googleAccountManager.getAccessToken(account, DriveScopes.DRIVE_FILE)); } } diff --git a/app/src/main/java/org/tasks/gtasks/GoogleAccountManager.java b/app/src/main/java/org/tasks/gtasks/GoogleAccountManager.java index aa5bb4331..32aa94f09 100644 --- a/app/src/main/java/org/tasks/gtasks/GoogleAccountManager.java +++ b/app/src/main/java/org/tasks/gtasks/GoogleAccountManager.java @@ -28,18 +28,21 @@ import org.tasks.R; import org.tasks.injection.ForApplication; 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( - @ForApplication Context context, PermissionChecker permissionChecker) { + @ForApplication Context context, PermissionChecker permissionChecker, Preferences preferences) { this.permissionChecker = permissionChecker; accountManager = android.accounts.AccountManager.get(context); + this.preferences = preferences; } public List getAccounts() { @@ -64,7 +67,7 @@ public class GoogleAccountManager { return getAccount(name) != null; } - public Bundle getAccessToken(String name, String scope) { + public String getAccessToken(String name, String scope) { assertNotMainThread(); Account account = getAccount(name); @@ -73,10 +76,13 @@ public class GoogleAccountManager { return null; } + boolean alreadyNotified = preferences.alreadyNotified(name, scope); + try { - return accountManager - .getAuthToken(account, "oauth2:" + scope, new Bundle(), true, null, null) - .getResult(); + String token = + accountManager.blockingGetAuthToken(account, "oauth2:" + scope, !alreadyNotified); + preferences.setAlreadyNotified(name, scope, Strings.isNullOrEmpty(token)); + return token; } catch (AuthenticatorException | IOException | OperationCanceledException e) { Timber.e(e); return null; @@ -114,6 +120,7 @@ public class GoogleAccountManager { .observeOn(AndroidSchedulers.mainThread()) .subscribe( bundle -> { + preferences.setAlreadyNotified(accountName, scope, false); Intent intent = (Intent) bundle.get(AccountManager.KEY_INTENT); if (intent != null) { activity.startActivity(intent); diff --git a/app/src/main/java/org/tasks/preferences/Preferences.java b/app/src/main/java/org/tasks/preferences/Preferences.java index 276d0c8e7..4b830e6f6 100644 --- a/app/src/main/java/org/tasks/preferences/Preferences.java +++ b/app/src/main/java/org/tasks/preferences/Preferences.java @@ -538,4 +538,12 @@ public class Preferences { public int getThemeBase() { return getInt(R.string.p_theme, ThemeBase.DEFAULT_BASE_THEME); } + + public boolean alreadyNotified(String account, String scope) { + return getBoolean(context.getString(R.string.p_notified_oauth_error, account, scope), false); + } + + public void setAlreadyNotified(String account, String scope, boolean value) { + setBoolean(context.getString(R.string.p_notified_oauth_error, account, scope), value); + } } diff --git a/app/src/main/java/org/tasks/preferences/fragments/Backups.kt b/app/src/main/java/org/tasks/preferences/fragments/Backups.kt index 786edf1a3..168fc3c03 100644 --- a/app/src/main/java/org/tasks/preferences/fragments/Backups.kt +++ b/app/src/main/java/org/tasks/preferences/fragments/Backups.kt @@ -5,6 +5,7 @@ import android.content.Intent import android.os.Bundle import androidx.preference.Preference import androidx.preference.SwitchPreferenceCompat +import com.google.api.services.drive.DriveScopes import com.todoroo.andlib.utility.AndroidUtilities import com.todoroo.astrid.gtasks.auth.GtasksLoginActivity import org.tasks.PermissionUtil @@ -55,44 +56,12 @@ class Backups : InjectingPreferenceFragment() { .show(parentFragmentManager, FRAG_TAG_EXPORT_TASKS) false } - - val googleDriveBackup = - findPreference(R.string.p_google_drive_backup) as SwitchPreferenceCompat - googleDriveBackup.onPreferenceChangeListener = - Preference.OnPreferenceChangeListener { preference: Preference, newValue: Any? -> - when { - newValue == null -> { - false - } - newValue as Boolean -> { - if (permissionRequestor.requestAccountPermissions()) { - requestGoogleDriveLogin() - } - false - } - else -> { - preference.summary = null - true - } - } - } } override fun onResume() { super.onResume() - val googleDriveBackup = - findPreference(R.string.p_google_drive_backup) as SwitchPreferenceCompat - val account = preferences.getStringValue(R.string.p_google_drive_backup_account) - if (preferences.getBoolean(R.string.p_google_drive_backup, false) - && googleAccountManager.canAccessAccount(account) - ) { - googleDriveBackup.isChecked = true - googleDriveBackup.summary = account - } else { - googleDriveBackup.isChecked = false - googleDriveBackup.summary = null - } + updateGoogleDriveCheckbox() } override fun onRequestPermissionsResult( @@ -140,17 +109,40 @@ class Backups : InjectingPreferenceFragment() { } } else if (requestCode == REQUEST_DRIVE_BACKUP) { val success = resultCode == RESULT_OK - (findPreference(R.string.p_google_drive_backup) as SwitchPreferenceCompat).isChecked = - success + preferences.setBoolean(R.string.p_google_drive_backup, success) + updateGoogleDriveCheckbox() if (!success && data != null) { toaster.longToast(data.getStringExtra(GtasksLoginActivity.EXTRA_ERROR)) } - } else { super.onActivityResult(requestCode, resultCode, data) } } + private fun updateGoogleDriveCheckbox() { + val account = preferences.getStringValue(R.string.p_google_drive_backup_account) + val pref = findPreference(R.string.google_drive_backup) as SwitchPreferenceCompat + pref.isChecked = preferences.getBoolean(R.string.p_google_drive_backup, false) + && googleAccountManager.canAccessAccount(account) + && !preferences.alreadyNotified(account, DriveScopes.DRIVE_FILE) + pref.summary = if (pref.isChecked) account else null + findPreference(R.string.google_drive_backup) + .setOnPreferenceChangeListener(this@Backups::onGoogleDriveCheckChanged) + } + + private fun onGoogleDriveCheckChanged(preference: Preference, newValue: Any?) = when { + newValue as Boolean -> { + if (permissionRequestor.requestAccountPermissions()) { + requestGoogleDriveLogin() + } + false + } + else -> { + preference.summary = null + true + } + } + private fun requestGoogleDriveLogin() { startActivityForResult( Intent(context, DriveLoginActivity::class.java), diff --git a/app/src/main/res/values/keys.xml b/app/src/main/res/values/keys.xml index fcd21fdd5..2c647ddff 100644 --- a/app/src/main/res/values/keys.xml +++ b/app/src/main/res/values/keys.xml @@ -287,4 +287,5 @@ https://tasks.org/subscribe show_subtasks wearable_notifications + notified_oauth_error_%s_%s diff --git a/app/src/main/res/xml/preferences_backups.xml b/app/src/main/res/xml/preferences_backups.xml index 99c28da5a..f09c7a347 100644 --- a/app/src/main/res/xml/preferences_backups.xml +++ b/app/src/main/res/xml/preferences_backups.xml @@ -6,8 +6,7 @@ android:title="@string/backup_directory" />