Archivos mensuales: Septiembre 2013

Compartir con Whatsapp en Phonegap (iOS y Android)

Una de las funcionalidades que últimamente me están demandado para las aplicaciones es la de poder compartir un texto o un foto por Whatsapp.

Al ser un producto de terceros y no tener una API pública, mi respuesta siempre era la de que no era posible. Hasta ahora, o hasta hace relativamente poco tiempo.

Buscando si era posible, me encontré con el siguiente FAQ la propia aplicación:

http://www.whatsapp.com/faq/en/iphone/23559013

Esto ya me dio una pista de hacia dónde orientar mis pruebas de cómo implementarlo.

La parte fácil es la de compartir texto, ya que usando el esquema de URL whatsapp:// se puede usar en ambas plataformas y es tan sencillo como poner un enlace o abrir una página:

<a href="whatsapp://send?text=Hello%2C%20World!">Whatsapp></a>
window.open('whatsapp://send?text=Hello%2C%20World!');

Para las imágenes las cosas se complica y tendremos que usar métodos diferentes según la plataforma.

iOS

Aquí vamos a usar la API de Document Iteration, básicamente es una API que nos permite sacar las aplicaciones que pueden abrir un tipo de documento, como sucede con Dropbox cuando te bajas un archivo y te da la opción de editarlo con aplicaciones externas que tengas instaladas.

Para usar esta API nos instalaremos el siguiente plugin de Phonegap:

https://github.com/phonegap/phonegap-plugins/tree/master/iOS/ExternalFileUtil 

Este plugin lo único que hace es abrir un cuadro con las aplicaciones compatibles con el tipo de documento que queremos compartir. Yo he modificado un par de cosas ya que el plugin devolvía siempre una cadena vacía abriera o no el cuadro, lo cual no es muy útil ya que no permite controlar si está o no instalado el Whatsapp en el dispositivo.

La modificación es en el fichero CDVExternalFileUtil.m y hay que cambiar la línea 64, de esto:

[controller presentOpenInMenuFromRect:rect inView:cont.view animated:YES];

a esto:

BOOL result = [controller presentOpenInMenuFromRect:rect inView:cont.view animated:YES];

Y la línea 66, de esto:

pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString: @""];

a esto:

pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString: (result ? @"YES" : @"NO")];

Una vez hechos esos cambios la manera de usar el plugin es la siguiente:

ExternalFileUtil.openWith('http://example.com/imagen.wai', "net.whatsapp.image", 
                function(result) { 
                    if (result == 'NO') {
                        // No está instalado el Whatsapp
                    }
                }
            );

El fichero imagen.wai es un JPG pero renombrado a .wai que es la extensión que usa el Whatsapp para saber que es una imagen. Para vídeos es .wam y para sonidos .waa.

Android

Aquí lo tenemos algo más fácil ya que mediante Intents podemos compartir una imagen.

Usaremos el siguiente plugin para poder lanzar Intents:

https://github.com/phonegap/phonegap-plugins/tree/master/Android/WebIntent

También es necesario modificarlo un poco ya que no tiene implementada la opción de lanzar directamente un Intent asociado a un paquete.

Por tanto los cambios a realizar son en el fichero  WebIntent.java, en la línea 54, añadir debajo la siguiente línea:

String pack = obj.has("package") ? obj.getString("package") : null;

En la línea 70, cambiar esto:

startActivity(obj.getString("action"), uri, type, extrasMap);

por esto:

startActivity(obj.getString("action"), uri, type, pack, extrasMap);

En la línea 158, añadir debajo lo siguiente:

if (pack != null) {
  i.setPackage(pack);
}

El uso sería el siguiente:

var extras = {};
                            extras[window.plugins.webintent.EXTRA_STREAM] = imagen_b64;

                            window.plugins.webintent.startActivity({ 
                                action: window.plugins.webintent.ACTION_SEND,
                                type: 'image/*', 
                                package: 'com.whatsapp',
                                extras: extras 
                                }, 
                                function() {
                                    // OK
                                }, 
                                function() {
                                    // El Whatsapp no está instalado.
                                }
                            );

La variable imagen_b64 será una imagen codificada en base64, podremos usar un fileReader si la imagen está en el dispositivo o un fileTransfer si está en un servidor.

[Editado]

Parce que lo del esquema de URL solo lo han implementado para iOS, para Android habrá que usar también el WebIntent:

var extras = {};
                            extras[window.plugins.webintent.EXTRA_TEXT] = 'Hola mundo';

                            window.plugins.webintent.startActivity({ 
                                action: window.plugins.webintent.ACTION_SEND,
                                type: 'text/plain', 
                                package: 'com.whatsapp',
                                extras: extras 
                                }, 
                                function() {
                                    // OK
                                }, 
                                function() {
                                    // El Whatsapp no está instalado.
                                }
                            );

[/Editado]