samsung - Android GoogleAuthUtil.getTokenWithNotification Intención de devolución de llamada no se dispara
porque no puedo hacer llamadas a un numero en especifico (4)
Tengo un servicio en segundo plano que llama a GoogleAuthUtl.getTokenWithNotification
y funciona correctamente, pero estoy intentando implementar la parte de devolución de llamada de esta función y eso no funciona correctamente.
He implementado un receptor de difusión y lo he agregado al manifiesto, también tengo una actividad en mi aplicación. A continuación se presentan las piezas de código relevantes.
GoogleAuthUtil.getTokenWithNotification
GoogleAuthUtil.getTokenWithNotification(this.getContext(), account, "oauth2:" + GmailScopes.GMAIL_SEND, null, new Intent(AuthReceiver.AUTH_INTENT));
AuthReceiver
public class AuthReceiver extends BroadcastReceiver
{
public final static String AUTH_INTENT = "com.testoauth.AUTH_INTENT";
public AuthReceiver()
{
}
@Override
public void onReceive(Context context, Intent intent)
{
Log.d("RECEIVER", "Received Auth broadcast.");
NotificationManager notificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.cancelAll();
}
}
AndroidManifest
<receiver android:name=".AuthReceiver" android:enabled="true" android:exported="true">
<intent-filter>
<action android:name="com.testoauth.AUTH_INTENT" />
</intent-filter>
</receiver>
No tengo ni idea de por qué no está recibiendo la emisión. No veo ninguna excepción en los registros y no hay indicios de que se haya llamado al receptor, ni siquiera se interrumpirá en un punto de interrupción al realizar la depuración. ¿Estoy haciendo algo incorrectamente?
EDITAR
Estoy usando min sdk 16 y target sdk 25
De la documentación de la API GoogleAuthUtil.getTokenWithNotification :
Este método se proporciona específicamente para tareas en segundo plano. En el caso de un error que necesite la intervención del usuario, este método se encarga de enviar notificaciones relevantes. Después de que el usuario direcciona la notificación, la devolución de llamada se difunde. Si el usuario cancela, entonces la devolución de llamada no se activa.
La devolución de llamada no se activa independientemente de que el usuario cancele o no. Aparte del ActivityManager
dice que se ha mostrado la notificación (se Displayed com.google.android.gms/.auth.uiflows.gettoken.GetTokenActivity
), no hay ninguna indicación de que la intención de transmisión especificada (en este caso com.testoauth.AUTH_INTENT
) tenga sido enviado en los registros. La "transmisión de autenticidad recibida". mensaje también está ausente de los registros.
El ejemplo de SDK incluido de esta funcionalidad ( <android-sdk>/extras/google/google_play_services/samples/auth/gau
) ni siquiera funciona.
He implementado una demo . He usado la última versión de auth gradle y está funcionando. Parece que podría haber un problema con la versión de autenticación
public class AuthActivity extends Activity {
private static final int AUTHORIZATION_CODE = 1993;
private static final int ACCOUNT_CODE = 1601;
private AuthPreferences authPreferences;
private AccountManager accountManager;
/**
* change this depending on the scope needed for the things you do in
* doCoolAuthenticatedStuff()
*/
private final String SCOPE = "https://www.googleapis.com/auth/googletalk";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
accountManager = AccountManager.get(this);
authPreferences = new AuthPreferences(this);
if (authPreferences.getUser() != null
&& authPreferences.getToken() != null) {
doCoolAuthenticatedStuff();
} else {
chooseAccount();
}
}
private void doCoolAuthenticatedStuff() {
// TODO: insert cool stuff with authPreferences.getToken()
Log.e("AuthApp", authPreferences.getToken());
clickSendEmail();
}
private void chooseAccount() {
// use https://github.com/frakbot/Android-AccountChooser for
// compatibility with older devices
Intent intent = AccountManager.newChooseAccountIntent(null, null,
new String[] { "com.google" }, false, null, null, null, null);
startActivityForResult(intent, ACCOUNT_CODE);
}
private void requestToken() {
Account userAccount = null;
String user = authPreferences.getUser();
for (Account account : accountManager.getAccountsByType("com.google")) {
if (account.name.equals(user)) {
userAccount = account;
Preferences.setAccount(AuthActivity.this,account.name, account.type);
break;
}
}
accountManager.getAuthToken(userAccount, "oauth2:" + SCOPE, null, this,
new OnTokenAcquired(), null);
}
/**
* call this method if your token expired, or you want to request a new
* token for whatever reason. call requestToken() again afterwards in order
* to get a new token.
*/
private void invalidateToken() {
AccountManager accountManager = AccountManager.get(this);
accountManager.invalidateAuthToken("com.google",
authPreferences.getToken());
authPreferences.setToken(null);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
if (requestCode == AUTHORIZATION_CODE) {
requestToken();
} else if (requestCode == ACCOUNT_CODE) {
String accountName = data
.getStringExtra(AccountManager.KEY_ACCOUNT_NAME);
authPreferences.setUser(accountName);
// invalidate old tokens which might be cached. we want a fresh
// one, which is guaranteed to work
invalidateToken();
requestToken();
}
}
}
private class OnTokenAcquired implements AccountManagerCallback<Bundle> {
@Override
public void run(AccountManagerFuture<Bundle> result) {
try {
Bundle bundle = result.getResult();
Intent launch = (Intent) bundle.get(AccountManager.KEY_INTENT);
if (launch != null) {
startActivityForResult(launch, AUTHORIZATION_CODE);
} else {
String token = bundle
.getString(AccountManager.KEY_AUTHTOKEN);
authPreferences.setToken(token);
doCoolAuthenticatedStuff();
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
private void clickSendEmail()
{
final Account account = Preferences.getAccount(this);
final String token = Preferences.getToken(this);
new Thread(new Runnable()
{
@Override
public void run()
{
try
{
Session session = Session.getDefaultInstance(new Properties(), null);
MimeMessage email = new MimeMessage(session);
email.setFrom(new InternetAddress(account.name));
//TODO: change email address to your email address for testing
email.addRecipient(javax.mail.Message.RecipientType.TO, new InternetAddress("[email protected]"));
email.setSubject("TEST OAUTH EMAIL");
email.setText("This is a test");
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
email.writeTo(bytes);
String encodedEmail = Base64.encodeBase64URLSafeString(bytes.toByteArray());
Message message = new Message();
message.setRaw(encodedEmail);
Intent intent = new Intent(AUTH_INTENT);
PendingIntent pendingIntent = PendingIntent.getBroadcast(AuthActivity.this, 0, intent, 0);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()
, pendingIntent);
String test = GoogleAuthUtil.getTokenWithNotification(AuthActivity.this, account, "oauth2:" + GmailScopes.GMAIL_SEND, null, intent);
GoogleCredential credential = new GoogleCredential();
credential.setAccessToken(test);
boolean changed = false;
if (!test.equals(token))
{
changed = true;
// Snackbar.make(AuthActivity.this.getView(), "TOKEN CHANGED", Snackbar.LENGTH_LONG).show();
Preferences.setToken(AuthActivity.this, test);
}
Gmail service = new Gmail.Builder(AndroidHttp.newCompatibleTransport(),
AndroidJsonFactory.getDefaultInstance(), credential)
.setApplicationName("Test OAuth").build();
service.users().messages().send("me", message).execute();
String msg = "Email sent";
if (changed)
msg = "TOKEN CHANGED: " + msg;
}
catch (MessagingException e)
{
Log.d( "ERROR", e.getMessage());
}
catch (GoogleJsonResponseException e)
{
if (e.getDetails().getCode() == 401)
{
try
{
Intent intent = new Intent(AUTH_INTENT);
GoogleAuthUtil.clearToken(AuthActivity.this, Preferences.getToken(AuthActivity.this));
GoogleAuthUtil.getTokenWithNotification(AuthActivity.this, account, "oauth2:" + GmailScopes.GMAIL_SEND, null, intent);
}
catch (Exception e1)
{
//ignore
}
}
}
catch (IOException e)
{
// Snackbar.make(AuthActivity.this.getView(), "ERROR", Snackbar.LENGTH_LONG).show();
Log.d( "ERROR", e.getMessage());
}
catch (Exception e)
{
//Snackbar.make(AuthActivity.this.getView(), "ERROR", Snackbar.LENGTH_LONG).show();
Log.d( "ERROR", e.getMessage());
}
}
}).start();
}
}
Intenté los siguientes errores en la API de Android 25, pero la función de devolución de llamada nunca se invocó:
- Sin internet
- El usuario no ha iniciado sesión todavía.
- El usuario no ha dado permiso para enviar correos electrónicos en su nombre.
- Google Play Services está deshabilitado
- Google Play Services no está actualizado
Si la invocación del método de devolución de llamada no es crucial para su caso de uso, puede seguir la API de inicio rápido de Android para Gmail para enviar correos electrónicos en nombre del usuario en Android. Marque Enviar correo electrónico para crear mensaje. También puede consultar MyGoogleAuthUtilApplication creada usando los tutoriales anteriores.
Espero que esto ayude.
No parece que alguien pueda dar una respuesta adecuada a esta pregunta; Un montón de sugerencias absolutamente excelentes sobre cómo solucionar el problema, pero nada responde a la pregunta real. Llegué a la conclusión de que esto debe ser un error en Android o en los servicios de Google Play. Desafortunadamente, he reportado este problema tanto al rastreador de problemas de Android como al foro de soporte de Google Play Services ... Ambos se identifican y se niegan a mirar el problema.
Migrar desde GoogleAuthUtil y Plus.API
Si se integró con el inicio de sesión de Google en el pasado con GoogleAuthUtil.getToken o Plus.API, debe migrar a la API de inicio de sesión más reciente para una mayor seguridad y una mejor experiencia de usuario.
Ref: https://developers.google.com/identity/sign-in/android/migration-guide
También mira esto si ayuda