2010-07-15 16 views
8

Estoy configurando OAuth para mi aplicación de Android. Para probarlo, hice lo siguiente: Agregué signpost-core-1.2.1.1.jar y signpost-commonshttp4-1.2.1.1.jar a mi proyecto, agregué las variables "CommonsHttpOAuthConsumer consumer" y "CommonsHttpOAuthProvider provider" e hice lo siguiente cuando se hace clic en el botón:Android OAuth: Excepción en retrieveAccessToken()

consumer = new CommonsHttpOAuthConsumer("xxx", "yyy"); 
provider = new CommonsHttpOAuthProvider("https://api.twitter.com/oauth/request_token", 
        "https://api.twitter.com/oauth/access_token", 
        "https://api.twitter.com/oauth/authorize"); 

oauthUrl = provider.retrieveRequestToken(consumer, "myapp://twitterOauth"); 
persistOAuthData(); 
this.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(oauthUrl))); 

persistOAuthData() hace lo siguiente:

protected void persistOAuthData() 
{ 
    try 
    { 
     FileOutputStream providerFOS = this.openFileOutput("provider.dat", MODE_PRIVATE); 
     ObjectOutputStream providerOOS = new ObjectOutputStream(providerFOS); 
     providerOOS.writeObject(this.provider); 
     providerOOS.close(); 

     FileOutputStream consumerFOS = this.openFileOutput("consumer.dat", MODE_PRIVATE); 
     ObjectOutputStream consumerOOS = new ObjectOutputStream(consumerFOS); 
     consumerOOS.writeObject(this.consumer); 
     consumerOOS.close(); 
    } 
    catch (Exception e) { } 
} 

Así, el consumidor y el proveedor se guardan antes de abrir el navegador, como se describe here.

En el método onResume() que cargue los datos del proveedor y del consumidor y hacer lo siguiente:

Uri uri = this.getIntent().getData(); 
    if (uri != null && uri.getScheme().equals("myapp") && uri.getHost().equals("twitterOauth")) 
    { 
     verifier = uri.getQueryParameter(oauth.signpost.OAuth.OAUTH_VERIFIER); 
     if (!verifier.equals("")) 
     { 
      loadOauthData(); 
      try 
      { 
       provider.retrieveAccessToken(consumer, verifier); 
      } 
      catch (OAuthMessageSignerException e) { 
       e.printStackTrace(); 
      } catch (OAuthNotAuthorizedException e) { 
       e.printStackTrace(); 
      } catch (OAuthExpectationFailedException e) { 
       e.printStackTrace(); 
      } catch (OAuthCommunicationException e) { 
       e.printStackTrace(); 
      }    
     } 
    } 

Por lo tanto, lo que funciona: 1) recibo un requestToken y una requestSecret. 2) Obtengo el oauthUrl. 3) Me dirigen a la página del navegador para autorizar mi aplicación 4) Me redireccionan a mi aplicación. 5) Obtengo el verificador. Pero la llamada a retrieveAccessToken (consumidor, verificador) falla con una OAuthCommunicationException que dice "Falló la comunicación con el proveedor del servicio: nulo".

¿Alguien sabe cuál podría ser el motivo? Algunas personas parecen tener problemas para obtener el requestToken, pero eso funciona bien. Me pregunto si podría ser un problema que mi aplicación también haya incluido apache-mime4j-0.6.jar y httpmime-4.0.1.jar, que necesito para la carga de varias partes.

Respuesta

13

Bien, lo descubrí. Tal vez esto sea útil para otros:

En primer lugar, no es necesario que guarde todo el objeto de consumidor y proveedor. Todo lo que necesita hacer es almacenar el requestToken y el requestSecret. Afortunadamente, esas son cadenas, por lo que no es necesario que las escriba en el disco ni nada. Solo guárdelos en las Preferencias compartidas o algo así.

Ahora, cuando usted es redireccionado por el navegador y su onResume() método se llama, simplemente hacer lo siguiente:

//The consumer object was lost because the browser got into foreground, need to instantiate it again with your apps token and secret. 
consumer = new CommonsHttpOAuthConsumer("xxx", "yyy"); 

//Set the requestToken and the tokenSecret that you got earlier by calling retrieveRequestToken. 
consumer.setTokenWithSecret(requestToken, tokenSecret); 

//The provider object is lost, too, so instantiate it again. 
provider = new CommonsHttpOAuthProvider("https://api.twitter.com/oauth/request_token", 
           "https://api.twitter.com/oauth/access_token", 
           "https://api.twitter.com/oauth/authorize");  
//Now that's really important. Because you don't perform the retrieveRequestToken method at this moment, the OAuth method is not detected automatically (there is no communication with Twitter). So, the default is 1.0 which is wrong because the initial request was performed with 1.0a. 
provider.setOAuth10a(true); 

provider.retrieveAccessToken(consumer, verifier); 

Eso es todo, puede recibir la señal y el secreto con getToken() y getTokenSecret(), ahora.

+0

Muchas gracias ... esto solucionó mi problema ... gran trabajo de Manuel – Panache

+0

Así, en su caso, la 'requestToken' que estableces en' consumer.setOkenWithSecret' es 'oauthUrl'? y ¿puedo preguntar qué es 'tokenSecret'? Gracias :) – dumbfingers

+0

Lo siento, creo que puedo averiguarlo, ¿se recupera el 'requestToken' utilizando' consumer.getToken() '? – dumbfingers

0

Hola Manuel veo que estás evitando el OAuthocalypse también! heres es un buen ejemplo para implementar OAuth para Twitter usando sharedPreferences para guardar requestToken y requestSecret, como su solución. http://github.com/brione/Brion-Learns-OAuth por Brion Emde

aquí tiene la esperanza video

esto ayuda a otros desarrolladores =)