Google Calendar API OAuth2 Problemas en Android Honeycomb
Estoy trabajando en una aplicación Android Honeycomb (v3.0) que tiene un requisito de comunicación con Google Calendar API. Me gustaría permitir que mi aplicación accediera a datos de calendario de una cuenta de Google en particular para leer y crear eventos.
Desafortunadamente, encontré un problema con la autorización usando OAuth2. Esto es lo que tengo hasta ahora:
- Cómo obtener vacaciones nacionales de un país seleccionado
- Evento de sincronización con google calendar desde android
- ¿Cómo acceder al Calendario del usuario en el dispositivo Android?
- Calendario de Android Las fechas de los eventos de todo el día están desactivadas en un día para GMT + x Áreas
- Cómo obtener eventos de google cuenta calendario en android?
1) La cuenta de Google cuyo calendario quisiera acceder está registrada en el dispositivo con el que estoy trabajando.
2) habilité la API de calendario dentro de la consola de API de Google en la cuenta.
3) Puedo acceder a esta cuenta usando el siguiente código:
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) Ahora quisiera obtener un AuthToken para usarlo cuando se comunica con el calendario. Seguí este tutorial , pero lo convertí a todo para trabajar con Google Calendar en lugar de con Google Tasks. Con éxito recupero un authToken
del AccountManager
con la cuenta que me gustaría utilizar usando getAuthToken
con AUTH_TOKEN_TYPE == "oauth2:https://www.googleapis.com/auth/calendar"
.
5) Aquí es donde comienzan los problemas. Ahora estoy en este 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) Aquí está la excepción devuelta por la última línea:
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) Según este video de la API de Google (espere un minuto más o menos para llegar al contenido aplicable), una razón para esta excepción puede ser el hecho de que no habilité el acceso a la API dentro de la Consola de API de Google para la cuenta. Sin embargo, si miras 2), puedes ver que lo hice.
8) Para mí, parece que el problema es que no pude establecer la clave de acceso Simple API correctamente, porque el método Calendar.setKey
está obsoleto. Dentro del tutorial de Google Tasks que he vinculado anteriormente, la clave se establece mediante Tasks.accessKey = "key"
. No estoy seguro de cómo conseguir esto trabajando con la API de calendario, sin embargo. He intentado varias cuentas de Google, que todo vino para arriba con la excepción de 5).
9) Quisiera señalar que el método tradicional de usar OAuth2 funcionó para mí. Aquí está el código que usé para eso:
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) Finalmente, mi pregunta: Me gustaría usar la cuenta de AccountManager en el propio dispositivo para recuperar un token OAuth2 de trabajo para usar con la API de Google Calendar. El segundo método no es útil para mí, porque el usuario tendrá que ir manualmente a su navegador web y obtener el código de autorización, que no es fácil de usar. ¿Alguien tiene alguna idea? Disculpas por el largo post, y gracias!
- Obtenga los horarios de inicio y fin de Google Calendar Events con google-java-api-client en Android
- Recuperación de datos del último evento agregado del calendario android
- Cómo adjuntar datos privados al evento de calendario android
- Autenticación con la API de Google mediante AccountManager
- Añadir evento de calendario en la aplicación para Android
- Dependencia apache cliente HTTP en android con API de Google
- Evento de calendario guardado localmente en el teléfono, pero no se puede sincronizar con Google Calendar.
- Api de Google Calendar para Android
Intente agregar un JsonHttpRequestInitializer al constructor y establezca su clave allí:
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();
Para responder no 10: básicamente he tenido que hacer lo que tenías que hacer para trabajar con TaskSample y luego usar la muestra de calendario de Android GData disponible aquí: http://code.google.com/p/google-api-java- Cliente / fuente / browse / calendario-android-sample / src / main / java / com / google / api / cliente / muestra / calendario / android / CalendarSample.java? Repo = muestras para obtener el AuthToken del propio AccountManager:
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(); }
- ¿Cuál es la diferencia entre android: layout_width y android: width
- Activos – "imágenes", "sonidos", y "webkit"?