viernes, 3 de agosto de 2012

Integrando LinkedIn en Android

En el post de hoy vamos a ver como podemos integrar de manera sencilla la red social de trabajo LinkedIn en nuestras aplicaciones Android. Para ello vamos a utilizar la librería linkedin-j, que encapsula las llamadas a la API Rest de LinkedIn y que además incorpora soporte para OAuth, el sistema de autenticación utilizado por la red social.

La principal ventaja del sistema OAuth es que permite que aplicaciones de terceros (por ejemplo la nuestra) se autentiquen en nombre de un usuario en un servicio (en este caso LinkedIn) sin necesidad de conocer las credenciales de acceso del usuario, utilizando en su lugar un token de acceso que especifica de manera explícita que permisos y cual es el tiempo de validez del acceso, lo que proporciona una mayor seguridad.

Lo primero que tenemos que hacer para integrar LinkedIn en nuestra aplicación es registrarla en la página de  desarrolladores de LinkedIn, donde nos darán dos claves (CustomerKey y CustomerSecret) que necesitaremos para autenticar nuestra aplicación. 

Una vez hecho esto, nos descargamos la librería linkedin-j, descomprimimos el zip con los 3 jars y los añadimos a las dependencias de nuestra aplicación Android y podemos empezar con la implementación en si:

 En la Activity principal (o en aquella en la que queramos iniciar el flujo de autenticación OAuth) tenemos que declarar un objeto del tipo LinkedInOAuthService, inicializándolo con los valores  que obtuvimos al registrar la aplicación (en el ejemplo están declarados cómo constantes)

private LinkedInOAuthService m_oauthService = LinkedInOAuthServiceFactory.getInstance().createLinkedInOAuthService(LinkedInOAuthParams.OAUTH_CONSUMER_KEY,LinkedInOAuthParams.OAUT_CONSUMER_SECRET);

A continuación iniciamos el proceso OAuth que nos permitirá obtener el token de acceso. Para ello se ejecuta el siguiente código (en el ejemplo al pulsar un botón de Login):

LinkedInRequestToken m_requestToken = m_oauthService.getOAuthRequestToken(LinkedInOAuthParams.OAUTH_CALLBACK_URL);
Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(m_requestToken.getAuthorizationUrl()));
  startActivity(i);

Con esto hacemos 2 cosas:

- Creamos una petición de token de acceso
- Iniciamos una activity que nos llevará a la página de LinkedIn donde el usuario podrá aceptar o rechazar el acceso de nuestra aplicación a su cuenta.

La clave en esta parte es el parámetro de la llamada  getOAuthRequestToken (definido también cómo una constante), que indica la URL de callback a la que la página de linkedin enviará el código de verificación necesario para obtener el token una vez que el usuario haya especificado si da acceso o no a nuestra aplicación. El problema es ¿cómo hacer  que el dispositivo Android del usuario reciba ese callback? ¿Y que URL debemos pasarle? Este problema lo resolvemos de la siguiente manera:

  •  La URL de callback nos la "inventamos". En el ejemplo está definida de la siguiente manera:
public static final String OAUTH_CALLBACK_SCHEME = "x-oauthflow-linkedin";
public static final String OAUTH_CALLBACK_HOST = "callback";
public static final String OAUTH_CALLBACK_URL = OAUTH_CALLBACK_SCHEME + "://" + OAUTH_CALLBACK_HOST;


Puede definirse la que uno quiera siempre que tenga el formato : schema://host
  • En el fichero Manifest.xml de nuestra aplicación definimos dentro del ámbito de la Activity que queramos que recoga el callback el siguiente filtro (marcado en negrita)
<activity
            android:name=".MainActivity"
            android:label="@string/title_activity_main" 
            android:launchMode="singleInstance">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
           <intent-filter>
  <action android:name="android.intent.action.VIEW" />
  <category android:name="android.intent.category.DEFAULT" />
  category android:name="android.intent.category.BROWSABLE" />
  <data android:scheme="x-oauthflow-linkedin"          
                      android:host="callback" />
    </intent-filter>
        </activity> 

Fijaos en que los campos android:scheme y android:host coinciden con la definición de la URL del punto anterior.

  Además en la definición de la Activity dentro del Manifest.xml indicamos que el atributo
   launchMode tenga el valor singleInstance, lo que hará que sólo haya una instancia de la misma en
   lugar de crearse una nueva cada vez que se le llama. 

  De vuelta al código de nuestra Activity sobreescribimos la llamada al método onNewIntent de la
    clase base de la siguiente forma:

    @Override
    protected void onNewIntent(Intent intent) 
    {
        super.onNewIntent(intent);
        Uri uri = intent.getData();

        if (uri != null && uri.toString().startsWith(LinkedInOAuthParams.OAUTH_CALLBACK_URL)) 
        {
            String verifier = intent.getData().getQueryParameter("oauth_verifier");
            LinkedInAccessToken accessToken =      
            m_oauthService.getOAuthAccessToken(m_requestToken, verifier);
            saveAccesToken(accessToken.getToken(), accessToken.getTokenSecret());
            showProfileActivity();
        }
    }

Como veis en este método obtenemos el parámetro que nos envía linkedin en el callback
('oauth_verifier') y lo utilizamos para obtener el token de acceso, utilizando también el
objeto m_requestToken.

Después con el token podemos empezar a hacer llamadas a la API de linkedin-j de la
manera que más nos convenga para nuestra aplicación: obtener información de
contactos, de recomendaciones, de grupos, de empleos...

En el caso del ejemplo lo que hacemos es guardar el token y mostrar una nueva Activity
donde lo utilizaremos para mostrar datos básicos del perfil del usuario:

//Creación del objeto LinkedInApiClient utilizando el accesToken
final LinkedInApiClientFactory factory = LinkedInApiClientFactory.newInstance(LinkedInOAuthParams.OAUTH_CONSUMER_KEY, LinkedInOAuthParams.OAUT_CONSUMER_SECRET);
final LinkedInApiClient client = factory.createLinkedInApiClient(accessToken);


//Obtención de los datos básicos del perfil de usuario
Person profile = client.getProfileForCurrentUser(EnumSet.of(ProfileField.FIRST_NAME, ProfileField.LAST_NAME, ProfileField.HEADLINE, ProfileField.PICTURE_URL));
m_txtName.setText(profile.getFirstName() + " " + profile.getLastName());
m_txtCurrent.setText(profile.getHeadline());

De esta sencilla manera podemos integrar nuestra aplicación con una de las redes sociales profesionales más importantes y grandes.

Podéis descargar el código de ejemplo en el siguiente enlace LinkedInAndroidIntegration.zip


1 comentario:

Roberto dijo...

Disculpa conectar contigo por este medio, pero estamos tratando de integrar imaxel en Magento para crear una tienda fotografica online y he visto que tienes experiencia en ambos softwares.
Quisiera saber si habria alguna posibilidad de que me comentaras que tan facil es la integracion y si podrias ayudarnos en el desarrollo.

Saludos

Roberto

Mi correso es rav.1971@hotmail.com