Utilizar Twitter en nuestra APP Android (Parte 3)

Bueno, después de lo visto en los otros 2 posts anteriores, teníamos pendiente capturar el regreso de twitter con la confirmación o no del permiso de uso de nuestra App.

Parte 1

Parte 2

Aquí es donde utilizaremos el famoso protcolo “mgl://” inventado por mí, de “Miguel” 😀

Tenemos que ir a la clase MainActivity y reescribir la función “onNewIntent” como sigue (esto es un poco así porque sí)


/**
 * Called when the OAuthRequestTokenTask finishes (user has authorized the
 * request token). The callback URL will be intercepted here.
 */
@Override
public void onNewIntent(Intent intent) {
	super.onNewIntent(intent);
	final Uri uri = intent.getData();
	SharedPreferences preferencias = this.getSharedPreferences("TwitterPrefs", MODE_PRIVATE);
	if (uri != null && uri.toString().indexOf(TwitterData.CALLBACK_URL) != -1) {
		Log.i("MGL", "Retrieving Access Token. Callback received : " + uri);
		new RetrieveAccessTokenTask(this, getConsumer(), getProvider(), preferencias).execute(uri);
		finish();
	}
}

Esto hace que en cada new Intent de la Actividad (Si alguien puede arrojar luz, se lo agradezco) se mire si tiene una URI con él y si esta URI tiene la URL del CALLBACK nuestro (mgl://mamor) pues actuamos en consecuencia, llamando a otra AsyncActivity como hicimos para pedir la autorización. Este hilo lo que hará es tomar los parámetros que nos devuelve Twitter… en caso de que el usuario haya aceptado, lo que nos devuelve son las credenciales del usuario para que podamos tener permiso para actuar en Twitter bajo su nombre.

Así que creamos la clase “RetrieveAccessTokenTask” con el siguiente código:


public class RetrieveAccessTokenTask extends AsyncTask<Uri, Void, Void> {

	private Context context;
	private OAuthProvider provider;
	private OAuthConsumer consumer;
	private SharedPreferences prefs;

	public RetrieveAccessTokenTask(Context context, OAuthConsumer consumer,
			OAuthProvider provider, SharedPreferences prefs) {
		this.context = context;
		this.consumer = consumer;
		this.provider = provider;
		this.prefs = prefs;
	}

	/**
	 * Retrieve the oauth_verifier, and store the oauth and
	 * oauth_token_secret for future API calls.
	 */
	@Override
	protected Void doInBackground(Uri... params) {
		final Uri uri = params[0];
		final String oauth_verifier = uri
			.getQueryParameter(OAuth.OAUTH_VERIFIER);

		try {
			provider.retrieveAccessToken(consumer, oauth_verifier);

			final Editor edit = prefs.edit();
			edit.putString(OAuth.OAUTH_TOKEN, consumer.getToken());
			edit.putString(OAuth.OAUTH_TOKEN_SECRET, consumer.getTokenSecret());
			edit.commit();

			String token = prefs.getString(OAuth.OAUTH_TOKEN, ");
			String secret = prefs.getString(OAuth.OAUTH_TOKEN_SECRET, ");

			consumer.setTokenWithSecret(token, secret);
			context.startActivity(new Intent(context, MainActivity.class));

			Log.i(TAG, "OAuth - Access Token Retrieved");

		} catch (Exception e) {
			Log.e(TAG, "OAuth - Access Token Retrieval Error", e);
		}

		return null;
	}
}

Esto lo que hace es guardar en SharedPreferences las credenciales secretas del usuario. Para saber más sobre SharedPreferences, puedes leer esto del blog de sgoliver.net

Para ver si se han almacenado las credenciales podemos abrir el DDMS y en el dispositivo encontraremos el XML 🙂

Gracias a tener estos datos, podremos hacer un tuit 😉 y esto lo haremos a través de la librería Twitter4j que os dije que teníamos que incluir.

Esto es muy facilito… vamos a usar una función de esta librería, la función “updateStatus”. Tened en cuenta que esto es un tutorial así rapidillo, por lo que hay muchas mejoras que tendréis que hacer o que veremos en otras entradas otro día, como por ejemplo lanzar una actividad u otra dependiendo de si el usuario ya nos aceptó en twitter… O dejar que el usuario borre sus credenciales y haga “logout” de la aplicación.

De momento nosotros vamos a hacer que la tarea asíncrona que recoge la vuelta de twitter, una vez haya terminado de hacer esto, envíe un Tuit dándome las gracias :-p

Para ello, si has leido la documentación de http://www.sgoliver.net que te dije anteriormente, sabrás que cuando la tarea asíncrona termina hace una llamada a un hook que es el método “onPostExecute”

En la clase RetrieveAccessTokenTask vamos a añadir este método

protected void onPostExecute(Boolean result) {
   if(result){
	String tuit = "Enviado desde Android siguiendo el tutorial https://mamorblog.wordpress.com/2013/04/17/utilizar-twitter-en-nuestra-app-parte-1/ gracias a @miguelsaddress";
	new MandaTuitTask(tuit, prefs).execute();
        Toast.makeText(this.context,"Acceso a twitter conseguido! Enviando el tuit",
                    Toast.LENGTH_SHORT).show();
   }else{
        Toast.makeText(this.context,"Acceso a twitter NO conseguido! ",
                    Toast.LENGTH_SHORT).show();
   }
}

Esto lo que hará es que cuando se termine de recoger el token desde twitter, automáticamente se mande este tuit. Normalmente no lo haríamos así, pero eso es para otros posts 🙂 Aquí es para aprovechar el tirón y mandar un tuit, para que se vea que después de liar todo esto para el oAuth, es realmente fácil.

Para mandar el tuit, lo haremos como se ve en la linea resaltada… Se hace en una tarea asíncrona porque hay que hacer una conexión con twitter y ya os dije que a partir de cierta versión de Android (no sé si la 3 o la 4) no se pueden hacer conexiones en el hilo principal… y si no lo hacemos así nos dará fallos y excepciones y nos hablará del Looper y de cosas horribles. Así que vamos a crear otra clase para mandar el tuit (aquí cada uno que se lo monte como más le guste… una clase asíncrona para cada petición de twitter me parece mucho, pero para esto, nos vale)

Vamos a crear esta clase

package com.mamoreno.twittertest;

import com.mamoreno.utils.TwitterUtils;
import android.content.SharedPreferences;
import android.os.AsyncTask;

public class MandaTuitTask extends AsyncTask<Void, Void, Void> {

	private String tuit;
	private SharedPreferences prefs;

	public MandaTuitTask( String tuit, SharedPreferences prefs){
		this.tuit = tuit;
		this.prefs = prefs;
	}

	@Override
	protected Void doInBackground(Void... params) {
		TwitterUtils.mandaTuit( this.tuit, this.prefs );
		return null;
	}

}

Solamente queremos que ejecute en segundo plano el envío del tuit… El envío en sí lo va a hacer otra clase con métodos estáticos llamada TwitterUtils… esto es por organizar un poco y por centralizar todo lo que podemos hacer con twitter en un solo lugar…

La clase TwitterUtils es la que realmente envía el tuit haciendo uso de Twitter4j

package com.mamoreno.utils;

import oauth.signpost.OAuth;
import twitter4j.Twitter;
import twitter4j.TwitterException;
import twitter4j.TwitterFactory;
import twitter4j.auth.AccessToken;
import android.content.SharedPreferences;
import android.util.Log;

public class TwitterUtils {

	public static void mandaTuit( String tuit, SharedPreferences prefs ){

    	AccessToken a = getAccessToken( prefs );
    	if( a!=null ){
	    	Twitter twitter = new TwitterFactory().getInstance();
	    	twitter.setOAuthConsumer(TwitterData.CONSUMER_KEY, TwitterData.CONSUMER_SECRET);
	    	twitter.setOAuthAccessToken(a);
	        try {
				twitter.updateStatus(tuit);
				Log.d("MGL", "+ twitter.getScreenName().toString()		);

			} catch (TwitterException e) {
				Log.e("MGL","TwitterExc: " + e.getMessage() 	 );
			}
    	}
	}

	private static AccessToken getAccessToken( SharedPreferences prefs ){
		String token = prefs.getString(OAuth.OAUTH_TOKEN, ");
    	String secret = prefs.getString(OAuth.OAUTH_TOKEN_SECRET, ");

    	if( secret.equals(") || token.equals(") ) return null;
    	Log.i("MGL", "TOKEN: " + token);
    	Log.i("MGL", "SECRET: " + secret);

    	return new AccessToken( token, secret );
	}

}

Para poder utilizar la librería Twitter4J, esta necesita tener un AccessToken, esto es, las credenciales del usuario, su autorización, para dárselas a twitter, y las usará CADA VEZ que interactúe con Twitter.

Para ello hacemos lo resaltado: Obtenemos una instancia de “Twitter”, le damos el consumer_key y el consumer_secret de nuestra aplicación y el AccessToken del usuario (que tomamos de lo que guardamos en SharedPreferences) y le decimos que mande un mensaje.

Y ya está! Así de simple!! (más de lo que parece una vez que le das una vueltecilla al proceso :D)

Ahora ejecuta la app… dale al botoncito que te llevará a twitter, confirma el acceso y a la vuelta, cuando vuelvas a ver la interfaz del botoncito corre a mirar tu twitter! a ver si te ha salido bien!

Quedaría pendiente:

  • A la vuelta de la confirmación, lanzar otra actividad con una interfaz diferente para mandar tuits o hacer lo que sea que haga nuestra aplicación…
  • Que al arrancar nuestra aplicación, identifique si ya hay credenciales guardadas y nos lleve a esa interfaz que comento.
  • Poder hacer “LogOut” es decir, borrar las credenciales de la app para que no pueda hablar en nuestro nombre o que la use otro usuario diferente.
  • Y por supuesto, gestión de errores, como por ejemplo: qué hacer si no se puede enviar el tuit o si el usuario no nos permite el acceso… habrá que poner algo en la interfaz, aunque sea un mensajito Toast, no? 🙂

Bájate el código desde GitHub AQUI!

 

Edit 26-julio-2013

OJO ha habido cambios en el API de twitter… averigua como hacer que te funcione esto!

Aqui

Anuncios

Etiquetado:,

3 pensamientos en “Utilizar Twitter en nuestra APP Android (Parte 3)

  1. Jorge 02/02/2014 en 17:11 Reply

    Hola, tengo un problema a la hora de las autorizaciones, sigo todas las instrucciones, incluso las de la nueva version de la API, pero a la hora de utilizar el boton de Twittear, SIEMPRE me entra a la web de acceso de twitter, incluso aunque tenga las preferencias guardadas, igualmente, aunque en la ventana del navegador le de a “no permitir” (Una vez permitidas anteriormente), el tweet se envía igual, así que supongo que mi problemá será al lanzar el navegador de acceso, que lo lanza siempre aunque tenga las preferencias guardadas. Gracias!

    • miguelbucarest 03/02/2014 en 16:28 Reply

      Hola Jorge, tienes el código subido a algún sitio?

      no prometo que pueda mirarlo porque ando muy, muy liado últimamente, pero por si saco un rato, eso que dices es muy raro pero me suena que me pasara una vez!

      Saludos

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: