2012-07-11 3 views
16

db 동기화를 처리하기 위해 SyncAdapter을 사용하여 새로운 Android 앱을 만들고 있습니다. 나는 모든 것을 갖추고 있으며 앱이 잘 작동하고 있지만 두 번 로그인 한 것으로 나타났습니다.SyncAdapters를 사용할 때 두 번 로그인하십시오.

AuthenticatorActivity 클래스 (확장 AccountAuthenticatorActivity)가 사용자와 암호의 유효성을 검사하면 첫 번째 로그인이 수행됩니다. 사용자와 암호가 올 경우

AuthenticatorActivity는 다음을 수행합니다

  • account는 그것이 intent.putExtra(AccountManager.KEY_AUTHTOKEN, authToken);

이를 사용하여 저장됩니다 mAccountManager.addAccountExplicitly()

  • authToken를 사용하여 생성 존재하지 않은 경우 기본적으로 Android 샘플에서 복사/붙여 넣기되었으므로 괜찮습니다.

    문제는 SyncAdapter 발사하고 AbstractAccountAuthenticator을 연장 Authenticator 클래스 내에

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

    getAuthToken() 방법을 사용하는 경우라는 점이다. 그리고이 방법 안에서 다시 로그인 끝점을 치고 있습니다.

    그 이후부터 authToken이 만료 될 때까지 로그인 엔드 포인트가 다시 히트되지 않습니다.

    이것은 나를 괴롭히는 것이 아니지만 로그인을 두 번하지 않도록하는 방법이 있는지 알고 싶습니다. 당신이 본 것처럼

  • +0

    번들에 토큰을 다시 전달하는 대신'AccountManager.setAuthToken()'을 사용하면 어떨까요? – alexanderblom

    +0

    @alexanderblom : 나는 그것을 시도했다. 차이 없음. – Macarse

    +1

    두 건의 로그인 뒤의 이유는 인증 토큰이 최신인지 확인하는 것이었지만 소스를 찾을 수 없었습니다. 나는 지난해 Google I/O에서 작년에 처음 출시되었을 때 C2DM 예제를 따라하려고했을 때 어딘가에서 읽은 것을 기억합니다 ... – Yenchi

    답변

    14

    의 SampleSyncAdapter에서 Authenticator.java

    이 클래스가 보여 있다는 흥미로운 점은 인증 프로세스의 일부로서 authTokens의 사용이다라고하지만. ... 이미 계정에 authToken이 저장되어 있으면 해당 authToken을 반환합니다. 우리가하지 않지만 사용자 이름과 비밀번호가 있으면 샘플 서비스와 대화하여 authToken을 가져옵니다.

    거짓말입니다. Authenticator.getAuthToken은 캐시 검사를하지 않고 토큰을 얻기 위해 네트워크에 도달합니다.

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

    주 프로젝트의 나머지 호출이 실패 할 때 종교적 AccountManager.invalidateAuthToken를 사용할 필요가 그렇지 않으면 실패 통화의 무한 루프와 바람거야 :

    이 솔루션은 누락 된 검사에 추가하는 것입니다 새로운 인증 토큰을 얻으려고 시도한 다음 동일한 캐시 된 인증 토큰이 반환 될 때 다시 실패합니다.

    +2

    전체 예제가 필요하다면 필자의 샘플 블로그 어댑터에서 동일한 기술을 사용했습니다. 그 주제에.여기에 동기화 어댑터에 대한 https://github.com/Udinic/SyncAdapter 블로그 포스트 : http://udinic.wordpress.com/2013/07/24/ 현재 샘플 응용 프로그램 코드를 볼 수 있습니다 write-your-own-android-sync-adaptor/ Authenticators에 대한 자세한 내용은이 문제에 대한 설명을 보려면 http://udinic.wordpress.com/2013/04/24/write-your-own- AccountAuthenticatorActivity를 확장하는 클래스에서 android-authenticator/ – Udinic

    +0

    을 호출하면 am.setAuthToken (String) 및 am.setPassword (String)을 호출합니다. AbstractAccountAuthenticator를 확장하는 클래스에서 am.peekAuthToken (account, authTokenType)을 호출합니다. 이것은 처음으로 null을 반환합니다. 그런 다음 계정의 사용자 이름과 계정 관리자 (am.getPassword (account))에 저장된 암호를 사용하여 로그인합니다. 그런 다음 authtoken은 getAuthToken에 의해 반환 된 번들을 통해 accountmanager에 저장됩니다. 누구나 am.setPassword()가 암호를 설정했지만 am.setAuthToken (String)이 설정되지 않은 이유를 알고 계십니까? – Ethan