Integración nativa con html5

Post on 05-Jan-2016

54 views 1 download

description

Integración nativa con html5. José Roberto ardila García 12 hit combo!. Porque es necesaria la integración nativa?. Hagamos un repaso de las características que nos ofrece PhoneGap Acelerómetro Cámara Brújula Acceso a contactos Archivos Geolocalización Media Network - PowerPoint PPT Presentation

Transcript of Integración nativa con html5

INTEGRACIÓN NATIVA CON HTML5

JOSÉ ROBERTO ARDILA GARCÍA

12 HIT COMBO!

PORQUE ES NECESARIA LA INTEGRACIÓN NATIVA?• HAGAMOS UN REPASO DE LAS CARACTERÍSTICAS QUE NOS OFRECE PHONEGAP

• ACELERÓMETRO

• CÁMARA

• BRÚJULA

• ACCESO A CONTACTOS

• ARCHIVOS

• GEOLOCALIZACIÓN

• MEDIA

• NETWORK

• NOTIFICACIONES (ALERTAS, SONIDOS, VIBRACIONES).

PERO QUE OCURRE SI SE NECESITA O APARECE UNA NUEVA CARACTERÍSTICA NUEVA O DIFERENTE EN LOS DISPOSITIVOS ANDROID?

• NFC

• IBEACONS (COMUNICACIÓN VÍA BLUETOOTH)

• WIDGETS

• TEXTTOSPEECH

• VOICETYPING

• REUTILIZAR CÓDIGO O ACTIVITIES QUE REALIZABAN OPERACIONES ESPECÍFICAS Y PUNTUALES (POR EJEMPLO ENVIAR CORREOS)…

QUE OCURRE SI PHONEGAP NO OFRECE SOPORTE PARA ELLO….

• LLORAR?

• ESPERAR A QUE EN ALGÚN MOMENTO PHONEGAP OFREZCA SOPORTE PARA ESAS CARACTERÍSTICAS?

• ENSUCIARSE LAS MANOS Y EXTENDER DE ALGUNA FORMA LA FUNCIONALIDAD DE PHONEGAP PARA DAR SOPORTE A LAS CARACTERÍSTICAS DESEADAS…

PHONEGAP PLUGINS

• POR MEDIO DE LOS “PLUGINS” ES POSIBLE EXTENDER LAS FUNCIONALIDADES DE PHONEGAP.

• A TRAVÉS DE LOS PLUGINS ES POSIBLE ACCEDER A CARACTERÍSTICAS NATIVAS DE LOS DISPOSITIVOS

• PHONEGAP UTILIZA ESE CONCEPTO PARA ACCEDER A LAS CARACTERÍSTICAS NATIVAS PREVIAMENTE MENCIONADAS.

• LOS PLUGINS SON DESARROLLADOS EN CÓDIGO NATIVO DE LA PLATAFORMA (EN EL CASO DE ANDROID: JAVA)

ENTENDIENDO LA ESTRUCTURA DE PLUGINS NATIVOS DE PHONEGAP

• LOS PLUGIN TIENEN 2 PARTES: UNA INTERFAZ BASADA EN JAVASCRIPT QUE PUEDE ACCEDERSE DESDE LA APLICACIÓN PHONEGAP (Y QUE SERÁ UTILIZADA EN TODAS LAS PLATAFORMAS) Y SU CORRESPONDIENTE CLASE NATIVA QUE REALIZARÁ LAS OPERACIONES NECESARIAS EN CÓDIGO NATIVO.

• LA INTERFAZ EN JAVASCRIPT INVOCARÁ AL CÓDIGO NATIVO UTILIZANDO EL MÉTODO CORDOVA.EXEC, EL CUAL INVOCARÁ A UN MÉTODO EXECUTE PRESENTE EN LAS CLASES NATIVAS.

ENTENDIENDO LA ESTRUCTURA DE PLUGINS NATIVOS DE PHONEGAP

EL MÉTODO CORDOVA.EXEC

• CORDOVA.EXEC(SUCCESSCALLBACK, FAILURECALLBACK, CLASS, METHOD, [ARGUMENTS]); 

• SUCCESSCALLBACK: SERÁ LA FUNCIÓN QUE SE QUIERA EJECUTAR CUANDO EL RESULTADO DE LA INVOCACIÓN SEA SATISFACTORIO.

• FAILURECALLBACK: SERÁ LA FUNCIÓN A EJECUTAR CUANDO EL RESULTADO DE LA INVOCACIÓN NO SEA SATISFACTORIO.

EL MÉTODO CORDOVA.EXEC

• CORDOVA.EXEC(SUCCESSCALLBACK, FAILURECALLBACK, CLASS, METHOD, [ARGUMENTS]);

• CLASS: SERÁ EL NOMBRE DE LA CLASE DE NUESTRO CÓDIGO NATIVO.

• METHOD: SERÁ EL NOMBRE DE LA ACCIÓN QUE SE VA A TENER EN CUENTA EN EL MÉTODO "EXECUTE" DE LA CLASE ANTERIOR QUE QUEREMOS INVOCAR.

• [ARGUMENTS]]: SERÁ UN ARRAY, GENERALMENTE EN FORMATO JSON, DONDE SE LE PASAN TODOS LOS PARÁMETROS DE ENTRADA AL MÉTODO INVOCADO.

CREACIÓN DE NUESTRO PRIMER PLUGIN

1. CREAMOS UN NUEVO PROYECTO PHONEGAP (OFFLINE) Y LO IMPORTAMOS A ECLIPSE:

$ cordova create C:\MyFirstPlugin com.unal.plugins CustomPluginActivity$cd C:\MyFirstPlugin $cordova platform add android

CREACIÓN DE NUESTRA CLASE NATIVA

• CREAMOS UNA NUEVA CLASE “HELLOPLUGIN” QUE EXTIENDA DE ORG.APACHE.CORDOVA.CORDOVAPLUGIN

• EN ESTA CLASE IRÁN LAS OPERACIONES NATIVAS QUE NECESITEMOS EJECUTAR

public boolean execute(String action, CordovaArgs args, CallbackContext callbackContext) throws JSONException {

boolean validAction = true;Log.d("Plugin ejecutando acción:",action);if (action.equals("nativeAction")) {

callbackContext.success(args.getString(0));}else {

validAction = false;}return validAction;

}

REGISTRAR EL NUEVO PLUGIN:

• EN NUESTRO ARCHIVO RES/XML/CONFIG.XML REGISTRAMOS NUESTRO NUEVO PLUGIN, DENTRO DE LOS TAGS “WIDGET”.

<feature name="HelloPlugin"> <param name="android-package" value="com.unal.plugins.plugin.HelloPlugin" /> </feature>

• MODIFICAMOS NUESTRO INDEX.XML PARA USAR NUESTRO NUEVO PLUGIN:

<!DOCTYPE html><html> <head> <title>Hola Plugin</title> </head> <body>

<h1>Prueba del nuevo Plugin!</h1>

<button onclick="callNativePlugin('success');">Click para invocar al PluginNativo con SUCCESS!</button> <button onclick="callNativePlugin('error');">Click para invocar al PluginNativo con ERROR!</button> <script type="text/javascript" src="cordova.js"></script> <script type="text/javascript" src="js/HelloPlugin.js"></script> </body></html>

Y DE LOS CALLBACKS CORRESPONDIENTES…

function callNativePlugin( returnSuccess ) { HelloPlugin.callNativeFunction( nativePluginResultHandler, nativePluginErrorHandler, returnSuccess ); }

function nativePluginResultHandler (result){ alert("SUCCESS: \r\n"+result ); } function nativePluginErrorHandler (error){ alert("ERROR: \r\n"+error ); }

CREAMOS NUESTRO ARCHIVO HELLOPLUGIN.JS ENCARGADO DE CONTENER LOS MÉTODOS DE EJECUCIÓN DEL PLUGIN NATIVO….

var HelloPlugin = { callNativeFunction: function (success, fail, resultType) { return cordova.exec( success, fail, "HelloPlugin", "nativeAction", [resultType]); } };

CREACIÓN DE UNA NUEVA CLASE NATIVAPARA INVOCAR UNA AGENDA NATIVA

• CREAMOS UNA NUEVA CLASE “CALENDARPLUGIN” QUE EXTIENDA DE ORG.APACHE.CORDOVA.CORDOVAPLUGIN

• EN ESTA CLASE IRÁN LAS OPERACIONES NATIVAS QUE NECESITEMOS EJECUTAR

public class CalendarPlugin extends CordovaPlugin {

public static final String ACTION_ADD_CALENDAR_ENTRY = "addCalendarEntry";

@Overridepublic boolean execute(String action, JSONArray args, CallbackContext

callbackContext) throws JSONException {

try { if (ACTION_ADD_CALENDAR_ENTRY.equals(action)) {

CREACIÓN DEL CALENDAR NATIVO (CON LOS PARÁMETROS TRAÍDOS DESDE PHONEGAP)

• YA QUE ESTAMOS TRABAJANDO DE FORMA NATIVA PODEMOS INVOCAR UN ACTIVITY EXTERNO DE LA MISMA FORMA QUE HARÍAMOS NORMALMENTE.

• UTILIZAMOS UN INTENT INTENT.ACTION_EDIT PARA CREAR LA AGENDA.

• LOS PARÁMETROS QUE NECESITAMOS PARA CREAR LA AGENDA SERÁN DATOS TRAÍDOS DESDE PHONEGAP.

• ESTOS PARÁMETROS VENDRÁN EN FORMATO JSON.

JSONObject arg_object = args.getJSONObject(0);

Intent calIntent = new Intent(Intent.ACTION_EDIT) .setType("vnd.android.cursor.item/event") .putExtra("beginTime",

arg_object.getLong("startTimeMillis")) .putExtra("endTime", arg_object.getLong("endTimeMillis")) .putExtra("title", arg_object.getString("title")) .putExtra("description",

arg_object.getString("description")) .putExtra("eventLocation",

arg_object.getString("eventLocation")); this.cordova.getActivity().startActivity(calIntent); callbackContext.success(); return true;

} callbackContext.error("Invalid action"); return false;} catch(Exception e) { System.err.println("Exception: " + e.getMessage()); callbackContext.error(e.getMessage()); return false;}

}

• PODEMOS AGREGAR MÚLTIPLES PLUGINS NATIVOS A UNA MISMA APLICACIÓN

<feature name="HelloPlugin"> <param name="android-package" value="com.unal.plugins.plugin.HelloPlugin" />

</feature>

<feature name="CalendarPlugin"> <param name="android-package" value="com.unal.plugins.plugin.CalendarPlugin" /></feature>

CREAMOS UN ARCHIVO LLAMADO CALENDARPLUGIN.JS Y UNA FUNCIÓN CREATEEVENT:

var calendarPlugin = { createEvent: function(title, location, notes, startDate, endDate, successCallback, errorCallback) { cordova.exec( successCallback, errorCallback, 'CalendarPlugin', 'addCalendarEntry',

[{"title": title,

"description": notes, "eventLocation": location, "startTimeMillis": startDate.getTime(), "endTimeMillis": endDate.getTime() }] ); }}

• CON ESTE MÉTODO ES QUE INICIALIZAMOS LOS DATOS DE NUESTRA AGENDA (ESTE CÓDIGO TAMBIÉN VA EN EL ARCHIVO CALENDARPLUGIN.JS)

function addToCal() { var startDate = new Date("July 19, 2013 8:00:00"); var endDate = new Date("July 19, 2013 18:00:00"); var notes = “llegar a tiempo al evento(desde Android)"; var title = "PhoneGap Day"; var location = "Portland, OR"; var notes = “llegar a tiempo!"; var success = function() { alert(“exito"); }; var error = function(message) { alert(“error! " + message); }; calendarPlugin.createEvent(title, location, notes, startDate, endDate, success, error);}

• PODEMOS AGREGAR A NUESTRA PÁGINA YA EXISTENTE EL NUEVO PLUGIN…

<!DOCTYPE html><html> <head> <title>Hola Plugin</title> </head> <body> <h1>Prueba del nuevo Plugin!</h1>

<button onclick="callNativePlugin('success');">Click para invocar al PluginNativo con SUCCESS!</button>

<button onclick="callNativePlugin('error');">Click para invocar al PluginNativo con ERROR!</button>

<button onclick="addToCal();">Click para crear una agenda </button>

<script type="text/javascript" src="js/CalendarPlugin.js"></script>

<script type="text/javascript" src="cordova.js"></script> <script type="text/javascript" src="js/HelloPlugin.js"></script>

</body></html>

AGREGAR TEXT TO SPEECH

• CREAMOS UNA NUEVA CLASE “TTSPLUGIN” QUE EXTIENDA DE ORG.APACHE.CORDOVA.CORDOVAPLUGIN

• EN ESTA CLASE IRÁN LAS OPERACIONES NATIVAS QUE NECESITEMOS EJECUTAR

• ESTE ES UN EJEMPLO DE COMO UTILIZAR DATOS QUE SE RECIBEN DESDE PHONEGAP.

• EN ESTA OCASIÓN UTILIZAREMOS 2 ACCIONES UNA PARA INICIAR EL SISTEMA TTS Y OTRO PARA EJECUTAR LA ACCIÓN DE CONVERSIÓN DE TEXTO A SONIDO, DE AHÍ QUE DECLARAREMOS LAS SIGUIENTES VARIABLES GLOBALES:

public static final String ACTION_NEW_TTS_INIT = "textToSpeechInit"; public static final String ACTION_NEW_TTS_TALK = "textToSpeechTalk";TextToSpeech ttobj;

@Overridepublic boolean execute(String action, final JSONArray args, final CallbackContext callbackContext) throws JSONException {

• DEBIDO A QUE LAS OPERACIONES TTS SON BASTANTE EXIGENTE DEBEMOS UTILIZAR MULTI-THREADING, ESTO NOS OBLIGA A QUE ALGUNOS PARÁMETROS TENGAN QUE SER DECLARADAS COMO FINAL:

if (ACTION_NEW_TTS_INIT.equals(action)) { cordova.getThreadPool().execute(new Runnable() { public void run() {

if(ttobj == null) {

ttobj=new TextToSpeech(cordova.getActivity().getApplicationContext(), new TextToSpeech.OnInitListener() { @Override public void onInit(int status) { if(status != TextToSpeech.ERROR){ ttobj.setLanguage(Locale.US); } } });

} } }); return true;}

else if(ACTION_NEW_TTS_TALK.equals(action)){ cordova.getThreadPool().execute(new Runnable() { public void run() { try { ttobj.speak(args.getString(0), TextToSpeech.QUEUE_FLUSH, null); callbackContext.success(); } catch(Exception e) { callbackContext.error(e.getMessage()); } } }); return true;}else{ return false;}

• AGREGAMOS NUESTRO PLUGIN (EN RES/XML/CONFIG.XML)

• Y CREAMOS UN NUEVO ARCHIVO JAVASCRIPT LLAMADO TTSPLUGIN.JS

<feature name="TTSPlugin"> <param name="android-package" value="com.unal.plugins.plugin.TTSPlugin" /></feature>

var TTSPlugin = { callTTSInitFunction: function (success, fail, resultType) { return cordova.exec( success, fail, "TTSPlugin", "textToSpeechInit", [resultType]); },

callTTSTalkFunction: function (success, fail, resultType) { return cordova.exec( success, fail, "TTSPlugin", "textToSpeechTalk", [resultType]); } };

• AGREGAMOS LAS FUNCIONES DE CALLBACK Y LAS QUE LLAMAREMOS DE NUESTRO CÓDIGO:

function callTTSInitPlugin(returnSuccess) { TTSPlugin.callTTSInitFunction( nativePluginResultHandler, nativePluginErrorHandler, returnSuccess ); }

function callTTSTalkPlugin( returnSuccess ) { TTSPlugin.callTTSTalkFunction( nativePluginResultHandler, nativePluginErrorHandler, returnSuccess ); } function nativePluginResultHandler (result) { alert("SUCCESS: \r\n"+result ); }

function nativePluginErrorHandler (error) { alert("ERROR: \r\n"+error ); }

• MODIFICAMOS NUESTRO ARCHIVO INDEX.JS PARA QUE QUEDE ASÍ (DE ESTA FORMA INICIALIZAMOS EL SISTEMA TTS AL CARGAR LA PÁGINA):

var app = {

// Application Constructor initialize: function() {

this.bindEvents(); },

bindEvents: function() {

document.addEventListener('deviceready', this.onDeviceReady, false); },onDeviceReady: function() {

callTTSInitPlugin('inicia'); },

};

• PARA FACILITAR LA MANIPULACIÓN DE DATOS, UTILIZAREMOS JQUERY, PARA ESTO DESCARGAREMOS EL ARCHIVO JAVASCRIPT DE JQUERY DESDE:

• HTTP://JQUERY.COM/DOWNLOAD/

• Y LO COPIAREMOS EN NUESTRA CARPETA ASSETS/WWW/JS

<div id="landmark-1" onsubmit="callTTSTalkPlugin($('#title').val());"><form><label for="title">TTS:</label><input id="title" name="title" type="text" />

<input type="submit" value="Click para TTS"></form></div>

<script type="text/javascript" src="js/index.js"></script> <script type="text/javascript" src="js/TTSPlugin.js"></script> <script type="text/javascript" src="js/jquery.js"></script> <script type="text/javascript"> app.initialize();

</script>

• AGREGAREMOS A NUESTRO ARCHIVO INDEX.HTML LO SIGUIENTE:

AGREGAR TEXT TO SPEECH

• CREAMOS UNA NUEVA CLASE “STTPLUGIN” QUE EXTIENDA DE ORG.APACHE.CORDOVA.CORDOVAPLUGIN

• EN ESTA CLASE IRÁN LAS OPERACIONES NATIVAS QUE NECESITEMOS EJECUTAR

• ESTE ES UN EJEMPLO DE COMO UTILIZAR DATOS QUE SE RECIBEN DESDE PHONEGAP.

public static final String ACTION_NEW_STT_TALK = "SpeechToTextTalk";CallbackContext callbackContext;protected static final int RESULT_SPEECH = 1;

@Overridepublic boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {

this.callbackContext = callbackContext; if(ACTION_NEW_STT_TALK.equals(action)) {

Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, "en-US"); this.cordova.getActivity().startActivityForResult(intent, RESULT_SPEECH); return true;

} else { return false; }}

public void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode) { case RESULT_SPEECH: if (resultCode == android.app.Activity.RESULT_OK && null != data) { ArrayList<String> text = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS); callbackContext.success(text.get(0)); } else { //code launched in case of error String message=data.getStringExtra("result"); callbackContext.error(message); } break; default: break; }}