5

Ich versuche, in meine Anwendung zum Abrufen für die Authentifizierung mit GoogleAccountCredential anmelden:Failing OAuth 2.0 Zugriffstoken auf Android-Emulator

mGoogleAccountCredential = GoogleAccountCredential.usingOAuth2(context, Arrays.asList(Scopes.EMAIL, Scopes.PLUS_LOGIN)); 
mGoogleAccountCredential.setSelectedAccountName(accountName); 
String token = mGoogleAccountCredential.getToken(); 

Es funktioniert gut auf realen Geräten, sondern auf dem Android-Emulator mGoogleAccountCredential.getToken() schlägt fehl mit folgenden Ausnahme:

java.lang.IllegalArgumentException: the name must not be empty: null 
03-01 19:41:31.604 3203-3361/com.myapp W/System.err:  at android.accounts.Account.<init>(Account.java:48) 
03-01 19:41:31.604 3203-3361/com.myapp W/System.err:  at com.google.android.gms.auth.GoogleAuthUtil.getToken(Unknown Source) 
03-01 19:41:31.604 3203-3361/com.myapp W/System.err:  at com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential.getToken(GoogleAccountCredential.java:255) 
  • Google-Dienste, die auf dem Emulator Play (GoogleApiAvailability.isGooglePlayServicesAvailable(context) liefert 0)
  • accountName gesetzt und richtig, wenn der setSelectedAccountName (auf "[email protected]")
  • alle Berechtigungen, dependecies und Konfigurationen gibt es in dem Projekt übergeben (wie in der Tat, es funktioniert auf allen realen Geräten)

Irgendein Hinweis warum funktioniert es nicht auf dem Emulator?

UPD:
Nach einem wenig in der Google-Code zu graben: das Problem tritt in setSelectedAccountName(accountName) Verfahren. Diese Methode fordert GoogleAccountManager an, ihm einen Account zu geben, der dem angegebenen Kontonamen zugeordnet ist. Wenn es kein solches Konto ist, wird der Kontoname null gesetzt wird:

public final GoogleAccountCredential setSelectedAccountName(String accountName) { 
    selectedAccount = accountManager.getAccountByName(accountName); 
    // check if account has been deleted 
    this.accountName = selectedAccount == null ? null : accountName; 
    return this; 
    } 

AccountManager, die wiederum alle bestehenden Konto übergeht und vergleicht ihre Namen auf den angegebenen Kontonamen. Wenn eine Übereinstimmung vorliegt, wird das entsprechende Konto zurückgegeben:

public Account getAccountByName(String accountName) { 
    if (accountName != null) { 
     for (Account account : getAccounts()) { 
     if (accountName.equals(account.name)) { 
      return account; 
     } 
     } 
    } 
    return null; 
    } 

    public Account[] getAccounts() { 
    return manager.getAccountsByType("com.google"); 
    } 

Die Sache ist die, dass getAccounts() kehrt leer Array auf dem Emulator. Auf einem echten Gerät gibt es jedoch eine richtige Liste zurück.

+0

Verwenden Sie Google API System Image? – Anthony

+0

Ja, natürlich, ich habe es in meiner Frage – meltedspark

+0

angegeben. Nur um sicher zu sein (da ich keine tiefe Erfahrung in diesem Thema habe), hast du das "Google APIs Item x86 System Image" benutzt, um dein virtuelles Gerät zu erstellen, und nicht nur "Artikel x86 Systembild"? Ich habe nicht gesehen, wo Sie dies angegeben haben (möglicherweise indirekt) – Anthony

Antwort

2

Nun, wie immer sind die Dinge einfacher als sie scheinen.
Danke an this post und an b1izzar für auf die richtige Antwort zeigen.

Alle echten Geräte, die ich überprüft habe, laufen Android 5.1 Lollipop.
Alle Emulatoren, die ich überprüft habe, laufen Android 6.0 Marshmallow.

Auf Marshmallow, d. H. Auf meinem Emulator ist es nicht genug, GET_ACCOUNTS Berechtigung in Manifest anzugeben. Es ist Pflicht diese Berechtigung zur Laufzeit mit einer bestimmten code beantragen:

anfordern Berechtigungen:

// Here, thisActivity is the current activity 
if (ContextCompat.checkSelfPermission(thisActivity, 
       Manifest.permission.READ_CONTACTS) 
     != PackageManager.PERMISSION_GRANTED) { 

    // Should we show an explanation? 
    if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity, 
      Manifest.permission.READ_CONTACTS)) { 

     // Show an expanation to the user *asynchronously* -- don't block 
     // this thread waiting for the user's response! After the user 
     // sees the explanation, try again to request the permission. 

    } else { 

     // No explanation needed, we can request the permission. 

     ActivityCompat.requestPermissions(thisActivity, 
       new String[]{Manifest.permission.READ_CONTACTS}, 
       MY_PERMISSIONS_REQUEST_READ_CONTACTS); 

     // MY_PERMISSIONS_REQUEST_READ_CONTACTS is an 
     // app-defined int constant. The callback method gets the 
     // result of the request. 
    } 
} 

Hinweis: in EibischGET_ACCOUNTS, WRITE_CONTACTS und READ_CONTACTS Berechtigungen sind in der gleichen Berechtigungsgruppe, also einmal READ_CONTACTS wird gewährt, GET_ACCOUNTS wird ebenfalls gewährt.

Anmerkung 2: in Android NougatGET_ACCOUNTS ist deprecated, so dass es Sinn READ_CONTACTS statt GET_ACCOUNT sogar in Eibisch zu bedienen ist.

1

Möglicherweise führt der Emulator eine ältere Version von Google Services aus. Es scheint, dass die neueste Version GoogleAuthException im Gegensatz zu IllegalArgumentException auslösen würde.

API Doc

public String getToken() 
       throws IOException, 
         com.google.android.gms.auth.GoogleAuthException 
Returns an OAuth 2.0 access token. 
Must be run from a background thread, not the main UI thread. 

Throws: 
IOException 
com.google.android.gms.auth.GoogleAuthException 
+0

IllegalArgumentException ist eine Laufzeitausnahme, keine überprüfte Ausnahme. Daher ist es nicht in der Signatur der Funktion angegeben. – meltedspark

+0

Sie haben Recht, Derp. –

1

Ich denke, dass das Problem ist, dass Sie ein physisches Gerät für die Entwicklung und das Testen, weil Google Play-Dienst kann nicht auf einem Emulator installiert werden verwenden müssen.

Ich sehe keinen anderen Grund, aber hier haben Sie eine code snippet von tasks-android-sample genommen, dass auch GoogleAccountCredential verwenden.

+0

Ich verwende das Bild, auf dem die Google Play-Dienste installiert sind ("Google API-Systemabbild"). In der Tat kann ich mich auf dem Emulator in meine Google Mail einloggen. – meltedspark

Verwandte Themen