7

Pracuję nad aplikacją Android Honeycomb (v3.0), która wymaga komunikacji z interfejsem API Kalendarza Google. Chciałbym zezwolić mojej aplikacji na dostęp do danych Kalendarza konkretnego konta Google w celu odczytywania i tworzenia zdarzeń.Google Calendar API OAuth2 - problemy z Androidem Honeycomb

Niestety, wystąpił problem z autoryzacją przy użyciu OAuth2. Oto, co mam do tej pory:

1) Konto Google, do którego chciałbym uzyskać dostęp, jest zarejestrowane na urządzeniu z Androidem, z którym współpracuję.

2) Włączyłem interfejs API Kalendarza w konsoli Google API na tym koncie.

3) Jestem w stanie uzyskać dostęp do konta za pomocą następującego kodu:

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) Chciałbym teraz, aby uzyskać AuthToken do użytku w komunikacji z kalendarza. Postępowałem zgodnie z tym tutorial, ale wszystko przekonwertowałem do pracy z Kalendarzem Google zamiast z Zadaniami Google. Pomyślnie pobieram authToken z AccountManager z kontem, którego chciałbym użyć, używając getAuthToken z AUTH_TOKEN_TYPE == "oauth2:https://www.googleapis.com/auth/calendar".

5) Oto, gdzie zaczynają się problemy. Jestem teraz w tym momencie:

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) Oto wyjątek zwrócony przez ostatniego wiersza:

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) Zgodnie z tym Google API Video (odczekać minutę lub tak aby dostać się do obowiązującej treści) powodem tego wyjątku może być fakt, że nie umożliwiłem dostępu API do konta w konsoli Google APIs. Jednak jeśli spojrzysz na 2), zobaczysz, że to zrobiłem.

8) Wydaje mi się, że problem polega na tym, że nie byłem w stanie poprawnie ustawić klucza dostępu do prostego interfejsu API, ponieważ metoda Calendar.setKey jest przestarzała. W samouczku zadań Google, który wcześniej połączono, klucz ustawia się przy użyciu Tasks.accessKey = "key". Nie wiem jednak, jak to działa z interfejsem Calendar API. Wypróbowałem wiele kont Google, z których każdy wymyślił wyjątek od 5).

9) Chciałbym podkreślić, że tradycyjna metoda korzystania z OAuth2 zadziałała właśnie dla mnie. Oto kod użyłem do tego:

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) Wreszcie, moje pytanie: Chciałbym użyć konta z AccountManager na samym urządzeniu w celu pobrania działającego OAuth2 żeton do użytku z Kalendarza Google API. Druga metoda nie jest dla mnie przydatna, ponieważ użytkownik będzie musiał ręcznie otworzyć przeglądarkę i uzyskać kod autoryzacji, który nie jest przyjazny dla użytkownika. Ktoś ma jakieś pomysły? Przepraszam za długi post i dziękuję!

+0

Witam, jestem w obliczu podobnego problemu, kiedyś ten kod fragmenty dostać kalendarza działających aplikacji, ale potem dostać 403 , dostęp zabroniony błąd, co uld u proszę pomóż, co powinienem zrobić w Androidzie? chociaż nie używam również opcji 8 jako opcji. proszę hlp. –

+0

Czego używasz jako opcji? Czy sprawdziłeś odpowiedź @ eltrl? – BVB

Odpowiedz

4

Spróbuj dodać JsonHttpRequestInitializer do konstruktora i ustawiania klucza tam:

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

Dziękuję, ale otrzymuję następujący błąd w Eclipse: 'Metoda setJsonHttpRequestInitializer (JsonHttpRequestInitializer) w typie Calendar.Builder nie ma zastosowania dla argumentów (nowy JsonHttpRequestInitializer() {})' – BVB

+0

Och, naprawiłem błąd (problem z importem) i zadziałało! Dziękuję bardzo! – BVB

+1

Nie ma problemu, te rzeczy nie są zbyt proste do zdiagnozowania, biorąc pod uwagę aktualny stan dokumentacji (beta). – eltrl

1

Aby odpowiedzieć na nie 10: Ja po prostu musiałem zrobić to, co trzeba było zrobić pracę z TaskSample a następnie użyć Android GData Kalendarz Sample dostępne tutaj: 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 uzyskać AuthToken z AccountManager samego:

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(); 
} 
Powiązane problemy