Ответ 1
Отказ от ответственности Я не сотрудник Google. Все, что я скажу ниже, это мои выводы из исследования подобных проблем.
Короткий ответ
Вы все делаете правильно. Это рекомендуемый способ входа в учетную запись Google. К сожалению, в этом механизме нет фактического обратного вызова, чтобы указать, что на самом деле пошло не так в вашем случае. Службы Google Play обрабатывают это, уведомляя пользователя о том, что его учетные данные устарели из-за уведомлений, которые вы можете увидеть ниже (сразу после изменения пароля).
Я бы порекомендовал сообщить об ошибке при добавлении дополнительных кодов результатов для вашего дела на https://issuetracker.google.com, так как это кажется заметным улучшением.
Длинный ответ
Google использует API учетной записи Android, как и все остальные (вы можете попробовать это сами). За кулисами это просто механизм поиска и хранения oauth-токенов.
Когда пароль был изменен, токен больше не действителен, и вы пытаетесь использовать его.
Это работает так, как разработчики Google Play Services решили реализовать его (поэтому я рекомендую вам сообщить об ошибке).
Например, AliExpress каким-то образом справится с этим и перенаправит пользователя на синюю страницу с просьбой снова войти в систему.
Aliexpress использует устаревший API. Как видите, диалоговое окно для выбора аккаунта имеет другой цвет и нет аватаров. API все еще можно использовать, но он может быть отключен в любое время (или нет). Я не рекомендую вам использовать это, но вот как это работает:
import com.google.android.gms.common.AccountPicker;
import com.google.android.gms.auth.GoogleAuthUtil;
import com.google.android.gms.auth.UserRecoverableAuthException;
void chooseAccount() {
Intent signInIntent = AccountPicker.newChooseAccountIntent(null, null, new String[]{GoogleAuthUtil.GOOGLE_ACCOUNT_TYPE}, true, null, null, null, null);
startActivityForResult(signInIntent, REQ_CHOOSE_ACCOUNT);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQ_CHOOSE_ACCOUNT) {
String email = data.getExtras().getString("authAccount");
// better do this in background thread
try {
GoogleAuthUtil.getToken(this, new Account(email, GoogleAuthUtil.GOOGLE_ACCOUNT_TYPE), "oauth2:https://www.googleapis.com/auth/userinfo.profile");
} catch (UserRecoverableAuthException recEx) {
Intent recoverIntent = recEx.getIntent();
// Will redirect to login activity
startActivityForResult(recoverIntent, REQ_RECOVER);
} catch (Exception e) {
Log.d(TAG, "caught exception", e);
}
}
}
Надеюсь, поможет!
UPD: новые API Google Play имеют ResolvableApiException, что расширяет ApiException, которую вы ловите. У него есть метод startResolutionForResult(), похожий на тот, который использовался в старых API. Но пакет, который вы получаете, не содержит информации о разрешении.
Bundle[{googleSignInStatus=Status{statusCode=unknown status code: 12501, resolution=null}}]
Если вы сообщите об ошибке, опубликуйте ее здесь, мы отметим ее)
Вы также можете отобразить диалоговое окно "Выбор учетной записи", используя API Android по умолчанию (минимум API 23).
Приведенный ниже код может быть использован для отображения "диалога выбора учетной записи" с использованием стандартных API управления учетными записями Android. Это новое и (надеюсь) не будет устаревшим некоторое время.
import android.accounts.Account;
import android.accounts.AccountManager;
// Unfortunately can be used only on API 23 and higher
Intent signInIntent = AccountManager.newChooseAccountIntent(
null,
null,
new String[] { "com.google" },
"Please select your account",
null,
null,
new Bundle());
startActivityForResult(signInIntent, REQ_SELECT_ACCOUNT);
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQ_SELECT_ACCOUNT) {
String accountName = data.getExtras().getString(AccountManager.KEY_ACCOUNT_NAME);
String accountType = data.getExtras().getString(AccountManager.KEY_ACCOUNT_TYPE);
// now you can call GoogleAuthUtil as in example above
}
}
Вы также можете получить список учетных записей Google, видимых для вашего приложения
Учетная запись становится видимой для вашего приложения после того, как пользователь попытался войти в приложение с такой учетной записью, используя один из указанных выше способов. Событие, если вход не был успешным (например, истек срок действия пароля), вы увидите эту учетную запись в списке (хотя не сможете определить, какая из них в случае нескольких учетных записей). Так что это может быть использовано в качестве обходного пути, но ограниченным образом.
import android.accounts.Account;
import android.accounts.AccountManager;
try {
// requires android.permission.GET_ACCOUNTS
Account[] accounts = AccountManager.get(this).getAccountsByType("com.google");
for (Account account : accounts) {
Log.d(TAG, "account: " + account.name);
}
} catch (Exception e) {
Log.i("Exception", "Exception:" + e);
}
Заключение К сожалению, я не нашел других способов доступа к данным аккаунта Google, чтобы обойти ваше дело с помощью современных API входа Google. Все расширенные API AccountManager требуют, чтобы у вас была та же подпись, что и у приложения владельца аккаунта (GMS - Google Mobile Services), что не соответствует действительности. Поэтому мы можем только запросить это у Google и надеяться, что это будет реализовано :(