7

Sto lavorando a un'applicazione Android Honeycomb (v3.0) che ha l'obbligo di comunicare con l'API di Google Calendar. Vorrei consentire alla mia applicazione di accedere a dati del calendario di un particolare account Google per poter leggere e creare eventi.Problemi OAuth2 di Google Calendar su Android Honeycomb

Sfortunatamente, ho riscontrato un problema con l'autorizzazione utilizzando OAuth2. Ecco cosa ho fino ad ora:

1) L'account Google di cui desidero accedere al calendario è registrato sul dispositivo Android con cui lavoro.

2) Ho abilitato l'API Calendar all'interno della Console API di Google sull'account.

3) sono in grado di accedere a questo account utilizzando il seguente codice:

AccountManager accountManager = AccountManager.get(this.getBaseContext()); 
Account[] accounts = accountManager.getAccountsByType("com.google"); 
Account acc = accounts[0]; // The device only has one account on it 

4) Vorrei ora per ottenere un authtoken essere utilizzata nelle comunicazioni con il calendario. Ho seguito questo tutorial, ma ho convertito tutto per funzionare con Google Calendar invece che con Google Task. Recupero con successo unoda AccountManager con l'account che vorrei utilizzare utilizzando getAuthToken con AUTH_TOKEN_TYPE == "oauth2:https://www.googleapis.com/auth/calendar".

5) Ecco dove iniziano i problemi. Ora sono a questo punto:

AccessProtectedResource accessProtectedResource = new GoogleAccessProtectedResource(tokens[0]); // this is the correct token 
HttpTransport transport = AndroidHttp.newCompatibleTransport(); 
Calendar service = Calendar.builder(transport, new JacksonFactory()) 
    .setApplicationName("My Application's Name") 
    .setHttpRequestInitializer(accessProtectedResource) 
    .build(); 
service.setKey("myCalendarSimpleAPIAccessKey"); // This is deprecated??? 
Events events = service.events().list("primary").execute(); // Causes an exception! 

6) Ecco l'eccezione restituito dalla ultima riga:

com.google.api.client.googleapis.json.GoogleJsonResponseException: 403 Forbidden 
{ 
    "code" : 403, 
    "errors" : [ { 
    "domain" : "usageLimits", 
    "message" : "Daily Limit Exceeded. Please sign up", 
    "reason" : "dailyLimitExceededUnreg", 
    "extendedHelp" : "https://code.google.com/apis/console" 
    } ], 
    "message" : "Daily Limit Exceeded. Please sign up" 
} 

7) In base a questa Google API Video (aspetta un minuto o giù di lì per arrivare al contenuto applicabile), una ragione per questa eccezione potrebbe essere il fatto che non ho abilitato l'accesso API all'interno della Console API di Google per l'account. Tuttavia, se guardi 2), puoi vedere che l'ho fatto.

8) Per me, sembra che il problema è che non sono riuscito a impostare correttamente la chiave di accesso API semplice, perché il metodo Calendar.setKey è obsoleto. Nell'esercitazione di Google Attività che ho precedentemente collegato, la chiave viene impostata utilizzando Tasks.accessKey = "key". Non sono sicuro di come farlo funzionare con l'API di Calendar, però. Ho provato più account Google, che hanno tutti generato un'eccezione da 5).

9) Vorrei sottolineare che il metodo tradizionale di utilizzo di OAuth2 ha funzionato per me. Ecco il codice che ho usato per questo:

HttpTransport TRANSPORT = new NetHttpTransport(); 
JsonFactory JSON_FACTORY = new JacksonFactory(); 
String SCOPE = "https://www.googleapis.com/auth/calendar"; 
String CALLBACK_URL = "urn:ietf:wg:oauth:2.0:oob"; 
String CLIENT_ID = "myClientID"; 
String CLIENT_SECRET = "myClientSecret"; 
String authorizeUrl = new GoogleAuthorizationRequestUrl(CLIENT_ID, CALLBACK_URL, SCOPE).build(); 
String authorizationCode = "???"; // At this point, I have to manually go to the authorizeUrl and grab the authorization code from there to paste it in here while in debug mode 

GoogleAuthorizationCodeGrant authRequest = new GoogleAuthorizationCodeGrant(TRANSPORT, JSON_FACTORY, CLIENT_ID, CLIENT_SECRET, authorizationCode, CALLBACK_URL); 
authRequest.useBasicAuthorization = false; 
AccessTokenResponse authResponse = authRequest.execute(); 
String accessToken = authResponse.accessToken; // gets the correct token 

GoogleAccessProtectedResource access = new GoogleAccessProtectedResource(accessToken, TRANSPORT, JSON_FACTORY, CLIENT_ID, CLIENT_SECRET, authResponse.refreshToken); 
HttpRequestFactory rf = TRANSPORT.createRequestFactory(access); 
AccessProtectedResource accessProtectedResource = new GoogleAccessProtectedResource(accessToken); 
HttpTransport transport = AndroidHttp.newCompatibleTransport(); 

Calendar service = Calendar.builder(transport, new JacksonFactory()) 
    .setApplicationName("My Application's Name") 
    .setHttpRequestInitializer(accessProtectedResource) 
    .build(); 

Events events = service.events().list("primary").execute(); // this works! 

10) Infine, la mia domanda: vorrei utilizzare l'account dal AccountManager sul dispositivo stesso al fine di recuperare un gettone OAuth2 lavorare per l'uso con Google Calendar API. Il secondo metodo non è utile per me, perché l'utente dovrà andare manualmente al proprio browser Web e ottenere il codice di autorizzazione, che non è facile da usare. Qualcuno ha qualche idea? Mi scuso per il lungo post, e grazie!

+0

ciao, sto affrontando un problema simile, ho usato questo frammenti di codice per ottenere un calendario applicazione in esecuzione, ma poi ho un 403 , accesso vietato errore, co ti prego di assistere, cosa dovrei fare in Android? anche se non sto usando il numero 8 come opzione. per favore hlp. –

+0

Cosa stai usando come opzione? Hai controllato la risposta di @ eltrl? – BVB

risposta

4

provare ad aggiungere un JsonHttpRequestInitializer al costruttore e impostando la chiave di là:

Calendar service = Calendar.builder(transport, new JacksonFactory()) 
.setApplicationName("My Application's Name") 
.setHttpRequestInitializer(accessProtectedResource) 
.setJsonHttpRequestInitializer(new JsonHttpRequestInitializer() { 
    public void initialize(JsonHttpRequest request) { 
     CalendarRequest calRequest = (CalendarRequest) request; 
     calRequest.setKey("myCalendarSimpleAPIAccessKey"); 
    } 

}).build(); 
+0

Grazie, ma ho ricevuto il seguente errore in Eclipse: 'Il metodo setJsonHttpRequestInitializer (JsonHttpRequestInitializer) nel tipo Calendar.Builder non è applicabile per gli argomenti (new JsonHttpRequestInitializer() {})' – BVB

+0

Oh my, ho corretto l'errore (problema di importazione) e ha funzionato! Grazie mille! – BVB

+1

Nessun problema, queste cose non sono molto banali da diagnosticare dato lo stato attuale (beta) della documentazione. – eltrl

1

Per rispondere no 10: ho praticamente dovuto fare ciò che si doveva fare lavorare con il TaskSample e quindi utilizzare l'Android GData Calendar campione disponibile qui: http://code.google.com/p/google-api-java-client/source/browse/calendar-android-sample/src/main/java/com/google/api/client/sample/calendar/android/CalendarSample.java?repo=samples per ottenere l'authtoken dal AccountManager stesso:

accountManager = new GoogleAccountManager(this); 
settings = this.getSharedPreferences(PREF, 0); 
gotAccount(); 

private void gotAccount() { 
     Account account = accountManager.getAccountByName(accountName); 
     if (account != null) { 
      if (settings.getString(PREF_AUTH_TOKEN, null) == null) { 
       accountManager.manager.getAuthToken(account, AUTH_TOKEN_TYPE, 
         true, new AccountManagerCallback<Bundle>() { 

          @Override 
          public void run(AccountManagerFuture<Bundle> future) { 
           try { 
            Bundle bundle = future.getResult(); 
            if (bundle 
              .containsKey(AccountManager.KEY_INTENT)) { 
             Intent intent = bundle 
               .getParcelable(AccountManager.KEY_INTENT); 
             int flags = intent.getFlags(); 
             flags &= ~Intent.FLAG_ACTIVITY_NEW_TASK; 
             intent.setFlags(flags); 
             startActivityForResult(intent, 
               REQUEST_AUTHENTICATE); 
            } else if (bundle 
              .containsKey(AccountManager.KEY_AUTHTOKEN)) { 
             setAuthToken(bundle 
               .getString(AccountManager.KEY_AUTHTOKEN)); 
             // executeRefreshCalendars(); 
            } 
           } catch (Exception e) { 
            handleException(e); 
           } 
          } 
         }, null); 
      } else { 
       // executeRefreshCalendars(); 
      } 
      return; 
     } 
     chooseAccount(); 
    } 

private void chooseAccount() { 
    accountManager.manager.getAuthTokenByFeatures(
      GoogleAccountManager.ACCOUNT_TYPE, AUTH_TOKEN_TYPE, null, 
      ExportClockOption.this, null, null, 
      new AccountManagerCallback<Bundle>() { 

       @Override 
       public void run(AccountManagerFuture<Bundle> future) { 
        Bundle bundle; 
        try { 
         bundle = future.getResult(); 
         setAccountName(bundle 
           .getString(AccountManager.KEY_ACCOUNT_NAME)); 
         setAuthToken(bundle 
           .getString(AccountManager.KEY_AUTHTOKEN)); 
         // executeRefreshCalendars(); 
        } catch (OperationCanceledException e) { 
         // user canceled 
        } catch (AuthenticatorException e) { 
         handleException(e); 
        } catch (IOException e) { 
         handleException(e); 
        } 
       } 
      }, null); 
} 

void setAuthToken(String authToken) { 
    SharedPreferences.Editor editor = settings.edit(); 
    editor.putString(PREF_AUTH_TOKEN, authToken); 
    editor.commit(); 
    createCalendarService(authToken); 
    try { 
     Events events = service.events().list("primary").execute(); 
    } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 

} 

private void createCalendarService(String authToken) { 
    accessProtectedResource = new GoogleAccessProtectedResource(authToken); 

    Log.i(TAG, "accessProtectedResource.getAccessToken() = " 
      + accessProtectedResource.getAccessToken()); 
    JacksonFactory jsonFactory = new JacksonFactory(); 
    service = com.google.api.services.calendar.Calendar 
      .builder(transport, jsonFactory) 
      .setApplicationName("Time Journal") 
      .setJsonHttpRequestInitializer(
        new JsonHttpRequestInitializer() { 
         @Override 
         public void initialize(JsonHttpRequest request) { 
          CalendarRequest calendarRequest = (CalendarRequest) request; 
          calendarRequest 
            .setKey("<YOUR SIMPLE API KEY>"); 
         } 
        }).setHttpRequestInitializer(accessProtectedResource) 
      .build(); 
} 
Problemi correlati