2012-07-11 47 views
16

我正在使用SyncAdapter創建一個新的Android應用程序來處理數據庫同步。 我有一切就位,應用程序工作正常,但我注意到,我登錄了兩次。使用SyncAdapters時登錄兩次

AuthenticatorActivity類(它延伸AccountAuthenticatorActivity)驗證用戶和密碼時,首次登錄時發生。

如果用戶和密碼都正確的AuthenticatorActivity那麼做:

  • 如果account不存在,它使用mAccountManager.addAccountExplicitly()
  • authToken使用intent.putExtra(AccountManager.KEY_AUTHTOKEN, authToken);

這是保存創建基本上是從Android樣本中複製/粘貼的,所以我猜這沒關係。

的問題是,當SyncAdapter啓動和使用

authtoken = mAccountManager.blockingGetAuthToken(account, 
      AuthenticatorActivity.PARAM_AUTHTOKEN_TYPE, true); 

getAuthToken()方法延伸AbstractAccountAuthenticatorAuthenticator類中被調用。在這個方法中,我再次敲擊登錄端點。

從此時起,直到authToken到期爲止,登錄端點才被再次命中。

這並不困擾我很多東西,但我想知道是否有辦法避免兩次登錄。

+0

如何使用'AccountManager.setAuthToken()'而不是將令牌返回到捆綁包中? – alexanderblom 2012-07-25 15:53:45

+0

@alexanderblom:我也試過。沒有不同。 – Macarse 2012-07-25 16:54:24

+1

我想兩個登錄背後的原因是爲了確保auth令牌是最新的,但我找不到來源支持我。我記得當我在去年的Google I/O中首次嘗試使用C2DM示例時,在某個地方閱讀它... – Yenchi 2012-07-30 16:13:02

回答

14

如你所見,雖然Authenticator.java在SampleSyncAdapter說

,這個類演示有趣的是使用authTokens作爲認證過程的一部分。 ...如果我們已經在帳戶中存儲了authToken,我們會返回該authToken。如果我們不這樣做,但我們確實有用戶名和密碼,那麼我們將嘗試與示例服務通話以獲取authToken。

這是一個謊言。 Authenticator.getAuthToken不對任何緩存檢查,它只是擊中網絡獲得令牌。

的解決方案是在缺少檢查補充:該項目的其餘部分需要宗教使用AccountManager.invalidateAuthToken當調用失敗,否則你會失敗的調用一個無限循環風

Authenticator.java: 
@Override 
public Bundle getAuthToken(AccountAuthenticatorResponse response, Account account, 
     String authTokenType, Bundle loginOptions) throws NetworkErrorException { 

    // check that authToken type supported 
    ... 

    // Check if we already have a cached token to return 
    final AccountManager am = AccountManager.get(mContext); 
    String cachedAuthToken = am.peekAuthToken(account, authTokenType); 
    if (cachedAuthToken != null) { 
     final Bundle result = new Bundle(); 
     result.putString(AccountManager.KEY_ACCOUNT_NAME, account.name); 
     result.putString(AccountManager.KEY_ACCOUNT_TYPE, Constants.ACCOUNT_TYPE); 
     result.putString(AccountManager.KEY_AUTHTOKEN, cachedAuthToken); 
     return result; 
    } 

    // Get new authToken from server 
    ... 

    // If all else fails, prompt the user for credentials 
    ... 
} 

注嘗試獲取新的身份驗證令牌,然後在返回相同的緩存身份驗證令牌時再次失敗。

+2

如果您需要一個完整的工作示例,我在我的博客文章的示例同步適配器上使用了相同的技術關於這個問題。 你可以看到示例應用程序代碼在這裏: https://github.com/Udinic/SyncAdapter 的博客文章在這裏同步適配器: http://udinic.wordpress.com/2013/07/24/寫你自己的安卓同步適配器/ 具體關於驗證器,解釋這個問題,你可以在這裏閱讀: http://udinic.wordpress.com/2013/04/24/write-your-own- android-authenticator/ – Udinic 2013-07-27 11:28:13

+0

在擴展AccountAuthenticatorActivity的類中,我調用am.setAuthToken(String)和am.setPassword(String)。 在擴展AbstractAccountAuthenticator的類中,我調用了am.peekAuthToken(account,authTokenType);第一次返回null。然後使用帳戶中的用戶名和帳戶管理器中保存的密碼(am.getPassword(account))登錄; 然後通過getAuthToken返回的包將authtoken保存在accountmanager中。任何人都知道爲什麼am.setPassword()成功設置密碼,但am.setAuthToken(String)不成功? – Ethan 2016-06-04 02:17:34