17

Ho un servizio in background che chiama GoogleAuthUtl.getTokenWithNotification e funziona correttamente ma sto cercando di implementare la parte di richiamata di questa funzione e che non funziona correttamente.android GoogleAuthUtil.getTokenWithNotification La richiamata di Intent non si attiva

Ho implementato un ricevitore broadcast e l'ho aggiunto al manifest, ho anche un'attività nella mia app. Di seguito sono riportati i pezzi di codice rilevanti.

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> 

Non ho idea del motivo per cui non sta ricevendo la trasmissione. Non vedo alcuna eccezione nei log e nessuna indicazione che il ricevitore è stato chiamato, non si romperà nemmeno su un breakpoint durante il debug. Sto facendo qualcosa in modo errato?

EDIT

sto usando min sdk 16 e sdk obiettivo del 25

Dalla documentazione GoogleAuthUtil.getTokenWithNotification API:

Questo metodo è espressamente previsto per le operazioni in background. Nell'evento di un errore che richiede l'intervento dell'utente, questo metodo si presta a per inviare una notifica pertinente. Dopo che l'utente ha risposto alla notifica , la chiamata viene trasmessa. Se l'utente annulla quindi , la richiamata non viene attivata.

La richiamata non viene attivata indipendentemente dall'annullamento dell'utente. A parte lo ActivityManager che dice che la notifica è stata visualizzata (Displayed com.google.android.gms/.auth.uiflows.gettoken.GetTokenActivity), non vi è alcuna indicazione che l'intento di trasmissione specificato (in questo caso com.testoauth.AUTH_INTENT) sia stato inviato nei registri. La "Trasmissione di ricezione ricevuta". il messaggio è anche assente dai log.

L'esempio di SDK incluso di questa funzionalità (<android-sdk>/extras/google/google_play_services/samples/auth/gau) non funziona nemmeno.

+0

Hai trovato una soluzione a questo problema? Ho provato lo stesso, ma non funziona anche per me. – Emanuel

+0

@Emanuel Purtroppo no, non l'ho fatto. – vane

+0

Stavo solo controllando, 'AuthReceiver.AUTH_INTENT = "com.testoauth.AUTH_INTENT";', giusto? *** /// *** Probabilmente non correlato: non utilizzare intenti impliciti, ci sono limitazioni in arrivo con ogni nuova versione della piattaforma [(Android O adesso)] (https://developer.android.com/preview/features /background.html#broadcasts) e il tuo caso non ha bisogno di Intenti impliciti. Basta creare 'new Intent (context, com.package.AuthReceiver.class)'. –

risposta

0

Non sembra che chiunque può dare una risposta adeguata a questa domanda; un sacco di suggerimenti assolutamente grandi su come aggirare il problema, ma niente rispondendo alla domanda vera e propria. Sono giunto alla conclusione che questo deve essere un bug in Android o nei Google Play Services. Purtroppo Ho segnalato questo problema sia per l'issue tracker Android e il Play Services forum di supporto ... Entrambi i quali Google puntano il dito contro l'altro e si rifiutano di guardare anche al problema.

1

Migrazione da GoogleAuthUtil e Plus.API

Se integrato con Google Sign-In in passato utilizzando GoogleAuthUtil.getToken o Plus.API, è necessario migrare alla nuova Sign-in e API per una maggiore sicurezza e una migliore esperienza utente.
Rif: https://developers.google.com/identity/sign-in/android/migration-guide

controllare anche questo fuori se aiuta

http://www.programcreek.com/java-api-examples/index.php?source_dir=AndroidAppDeployer-master/AndroidAppDeployer/src/com/appjma/appdeployer/service/DownloadService.java

http://www.programcreek.com/java-api-examples/index.php?source_dir=AndroidAppDeployer-master/AndroidAppDeployer/src/com/appjma/appdeployer/receiver/AuthReceiver.java

+0

Questi 2 esempi ho provato prima e non funzionano neanche. Sto iniziando a pensare che si tratti di un bug reale con i servizi di Google Play. Per quanto riguarda Plus.API, da quello che ho capito è l'utente che accede a google e dà all'app l'accesso ad alcuni aspetti dei propri account mentre l'app che sto cercando di creare ha solo bisogno e vuole solo l'accesso per inviare e-mail e usare GoogleAuthUtil ci consente di visualizzare l'app connessa e a cosa è necessario accedere nell'account Google dell'utente. – vane

1

ho provato dopo gli errori in API Android 25, ma la funzione di callback era mai invocato:

  • No Internet
  • L'utente non ha effettuato l'accesso ancora
  • L'utente non ha dato il permesso di inviare e-mail sul suo conto/
  • Google Play Services è disattivato
  • Google Play Services è fuori dalla data di

Se il metodo di callback invocazione non è cruciale per il vostro caso d'uso, è possibile seguire Android Quickstart for Gmail API per inviare messaggi di posta elettronica per conto dell'utente in E roid. Controlla Sending Email per creare un messaggio. È inoltre possibile controllare MyGoogleAuthUtilApplication creati utilizzando il tutorial di cui sopra.

Spero che questo aiuti.

+0

Il problema con questo metodo è che l'esempio dell'API di Gmail si basa su 'MimeMessage', che è in una lib che non è disponibile per Android, o almeno non è molto chiaro dove quella lib sia per Android. – vane

+0

Sì, ho avuto problemi con la ricerca della libreria per 'MimeMessage'.Alla fine, "https://mvnrepository.com/artifact/com.sun.mail/android-mail" <- questa libreria ha funzionato per me. Puoi controllare il mio progetto GitHub. – BhalchandraSW

+0

Ho provato questo ed è un'ottima soluzione per l'invio di e-mail (che migrerò a) ma non risolve ancora il problema di callback. Se lo uso dovrò comunque avere una richiamata o creare la mia notifica e non usare quella integrata di Android. – vane

1

ho implementato demo ho usato più recente versione Gradle autenticazione e il suo funzionamento. Il suo aspetto che ci potrebbero essere problemi con la versione di autenticazione

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(); 
    } 
} 
+0

Questo non risolve il mio problema in alcun modo. Il 'AccountManager.getAuthToken' è solo per le operazioni in foreground. Ho bisogno di usare 'GoogleAuthUtil.getTokenWithNotification' perché viene eseguito in un servizio in background e mette anche una notifica nella barra di stato e getAuthToken no. – vane

+0

oh adesso è troppo tardi qui. Controllerò il servizio domani. Ma ho una domanda, devi usare AccountManager solo 1 volta per ottenere il token, quindi non ce n'è bisogno. Quindi non ti va bene se prendi token dall'interfaccia utente? Anche senza ui come l'utente può selezionare l'account? –

+0

No, ho bisogno di controllare il token in un servizio in background quando il servizio è avviato. Questo deve essere in grado di mostrare una notifica all'utente se ha rimosso l'autorizzazione per l'app dalle impostazioni dell'account google prima che il servizio venga chiamato in un secondo momento. Altrimenti, non sarebbe in grado di utilizzare il token poiché il token non è più valido. – vane

Problemi correlati