Download - Integración nativa con html5

Transcript
Page 1: Integración nativa con html5

INTEGRACIÓN NATIVA CON HTML5

JOSÉ ROBERTO ARDILA GARCÍA

12 HIT COMBO!

Page 2: Integración nativa con html5

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).

Page 3: Integración nativa con html5

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)…

Page 4: Integración nativa con html5

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…

Page 5: Integración nativa con html5

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)

Page 6: Integración nativa con html5

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.

Page 7: Integración nativa con html5

ENTENDIENDO LA ESTRUCTURA DE PLUGINS NATIVOS DE PHONEGAP

Page 8: Integración nativa con html5

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.

Page 9: Integración nativa con html5

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.

Page 10: Integración nativa con html5

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

Page 11: Integración nativa con html5

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

Page 12: Integración nativa con html5

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;

}

Page 13: Integración nativa con html5

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>

Page 14: Integración nativa con html5

• 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>

Page 15: Integración nativa con html5

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 ); }

Page 16: Integración nativa con html5

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]); } };

Page 17: Integración nativa con html5
Page 18: Integración nativa con html5

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

Page 19: Integración nativa con html5

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)) {

Page 20: Integración nativa con html5

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.

Page 21: Integración nativa con html5

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;

Page 22: Integración nativa con html5

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

}

Page 23: Integración nativa con html5

• 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>

Page 24: Integración nativa con html5

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() }] ); }}

Page 25: Integración nativa con html5

• 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);}

Page 26: Integración nativa con html5

• 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>

Page 27: Integración nativa con html5

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.

Page 28: Integración nativa con html5

• 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;

Page 29: Integración nativa con html5

@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:

Page 30: Integración nativa con html5

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;}

Page 31: Integración nativa con html5

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;}

Page 32: Integración nativa con html5

• 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]); } };

Page 33: Integración nativa con html5

• 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 ); }

Page 34: Integración nativa con html5

• 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'); },

};

Page 35: Integración nativa con html5

• 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

Page 36: Integración nativa con html5

<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:

Page 37: Integración nativa con html5
Page 38: Integración nativa con html5

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.

Page 39: Integración nativa con html5

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; }}

Page 40: Integración nativa con html5

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; }}