5

我試圖登錄到使用GoogleAccountCredential爲驗證我的應用程序獲取的OAuth 2.0訪問令牌:未能在Android模擬器

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

它可以在真實設備就好了,但在Android模擬器mGoogleAccountCredential.getToken()失敗但下列情況除外:

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) 
  • 谷歌播放目前服務於模擬器(GoogleApiAvailability.isGooglePlayServicesAvailable(context)返回0)
  • accountName設置正確傳遞給setSelectedAccountName(設置爲"[email protected]"
  • 所有權限,依賴條件時,並在項目中存在的結構(如事實上,它適用於所有的真實設備)

任何線索爲什麼它不在仿真器上工作?

UPD:
在谷歌的代碼挖了一下後:發生在setSelectedAccountName(accountName)方法的問題。此方法要求GoogleAccountManager給他一個與給定帳戶名稱關聯的帳戶。如果沒有這樣的帳戶,帳戶名被設置爲null

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,反過來,越過所有的現有帳戶,他們的名字比較給定的帳戶名。如果有匹配,則返回相應的帳戶:

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"); 
    } 

的事情是,getAccounts()回報在模擬器空數組。然而,在真實的設備上,它會返回一個正確的列表。

+0

您是否使用Google API系統映像? – Anthony

+0

當然,我在我的問題中指定了它 – meltedspark

+0

爲了確保(因爲我對此主題的經驗不深),您是否使用「Google API項目x86系統映像」構建虛擬設備,而不僅僅是「項目x86系統映像」?我沒有看到您指定的位置(可能是間接的) – Anthony

回答

2

那麼,一如往常事情比看起來容易。
感謝this郵政和b1izzar指向正確的答案。

我檢查的所有真實設備都在運行Android 5.1棒棒糖
我檢查的所有模擬器正在運行Android 6.0棉花糖

棉花糖,即在我的模擬器上,僅指定清單中的GET_ACCOUNTS權限是不夠的。這是強制性在運行時與特定code請求該權限

請求的權限:

// 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. 
    } 
} 

注:棉花糖GET_ACCOUNTSWRITE_CONTACTSREAD_CONTACTS權限在同一個權限組中,所以一次是READ_CONTACTS被授予,GET_ACCOUNTS也被授予。

注2:Android的牛軋糖GET_ACCOUNTSdeprecated,所以是有意義的,即使在棉花糖使用READ_CONTACTS代替GET_ACCOUNT

1

模擬器可能運行的是舊版本的Google服務。看來最新版本會拋出GoogleAuthException而不是IllegalArgumentException。

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是一個運行時異常,而不是已檢查的異常。因此在函數的簽名中沒有指定。 – meltedspark

+0

你說得對,derp。 –

1

我覺得現在的問題是,你必須使用一個物理設備的開發和測試,因爲谷歌播放服務不能在模擬器上進行安裝。

我沒有看到另外一個原因,但在這裏,你必須從tasks-android-sample採取code snippet也使用GoogleAccountCredential

+0

我使用安裝了Google Play服務的圖像(「Google API系統圖像」)。事實上,我可以在模擬器上登錄到我的Gmail。 – meltedspark