Nota: He publicado una versión más actualizada de este post para la versión 3 de Ionic.
En este post vamos a ver cómo podemos utilizar los plugins de Cordova con Ionic 2. Hemos mencionado varias veces Cordova y que Ionic depende de Cordova para desplegarse de forma nativa, ¿qué quiere decir esto exactamente?
Una de las desventajas de crear aplicaciones web para dispositivos móviles es que, al contrario de las aplicaciones nativas, no tienen acceso a funcionalidades nativas de los dispositivos como por ejemplo, la cámara, el GPS, la galería de fotos, funcionalidades de redes sociales de forma nativa y muchas otras.
Es aquí cuando Cordova viene al rescate. Cordova agarra todo el HTML, CSS, recursos y JavaScript de tu aplicación (en el caso de Ionic 2 sería tu aplicación basada en Angular 2) y lo coloca en un contenedor nativo, dependiendo de la plataforma, este puede ser iOS o Android, y provee un API de JavaScript, con el cual, desde nuestro código de la aplicación podemos acceder a las funcionalidades nativas del dispositivo.
Sin embargo, con sólo utilizar Cordova tal cual, no podemos utilizar dichas funcionalidades nativas, para ello tenemos que escribir plugins de Cordova, los cuales se escriben utilizando los lenguajes de programación que normalmente utilizaríamos cuando escribimos aplicaciones nativas para poder interactuar con las funcionalidades del dispositivo, y con el API de Javascript de Cordova, creamos una interfaz javascript para el plugin, siendo este el puente entre lo nativo y la aplicación HTML, CSS y JavaScript (Angular en el caso de Ionic).
Es importante destacar que es posible escribir una aplicación utilizando Cordova sin necesidad de utilizar Ionic; Ionic no es más que el framework para desarrollar la aplicación, igual podemos utilizar nuesto propio código HTML, CSS y Javascript u otro framework como por ejemplo jQuery Mobile y en cualquiera de los casos podemos hacer uso de los plugins de Cordova.
Existen decenas de plugins ya escritos por desarrolladores listos para utilizar en nuestra aplicación, cuando necesitemos utilizar alguna funcionalidad nativa del dispositivo es recomendable primero hacer un pequeño estudio de los plugins disponibles antes de escribir el nuestro.
Si te interesa desarrollar tu propio plugin, puedes consultar la guía de desarrollo de plugins de Cordova.
Ionic Native
Ionic tiene un proyecto llamado Ionic Native en el cual seleccionó un conjunto de Cordova plugins y creó wrappers basados en ES5/ES6/TypeScript los cuales facilitan el uso de estos plugins en Ionic 2, ya que por defecto, para el desarrollo de las aplicaciones en Ionic 2, se utiliza TypeScript.
Segun su documentación, Ionic Native envuelve las llamadas de retorno (callbacks) de los plugins en “promesas” u “observables” (Promise, Observable) con el objetivo de proveer una interfaz común para todos los plugins que forman parte de Ionic Native y asegurar que los eventos nativos provoquen detección de cambios en Angular 2.
Un ejemplo
Cuando creamos un proyecto utilizando ionic start, por defecto ya viene incluido Ionic Native, de cualquier modo, la forma de instalarlo es con npm:
npm install ionic-native --save
Vamos a ver un ejemplo de cómo utilizar un plugin que forma parte de Ionic Native, para ello primero tenemos que crear un proyecto de Ionic, vamos a utilizar el proyecto de ejemplo del post anterior.
El plugin que vamos a utilizar es Camera, el cual permite tomar fotos con la cámara del dispositivo. Para adicionarlo al proyecto utilizamos un comando del CLI de Ionic que se llama plugin:
ionic plugin add cordova-plugin-camera
Este comando forma parte del CLI de Cordova también, por lo que de igual manera podemos utilizar:
cordova plugin add cordova-plugin-camera
Si en algún momento deseamos eliminar el plugin, basta con ejecutar este comando pero utilizando el parámetro remove en lugar de add.
Para el ejemplo, vamos a colocar un botón en el tab “Home” llamado “Tomar foto” el cual debe permitirnos tomar una foto y luego que la foto sea tomada la mostraremos en el mismo tab.
Vamos a modificar el template HTML del componente de Ionic (o página) que corresponde al tab “Home” el cual se encuentra en el archivo: ejemplo\src\pages\home\home.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<ion-header> | |
<ion-navbar> | |
<ion-title>Home</ion-title> | |
</ion-navbar> | |
</ion-header> | |
<ion-content padding> | |
<button ion-button full (click)="takePicture()">Tomar foto</button> | |
</ion-content> |
Y modificamos el código de la página del tab “Home” que se encuentra en el archivo: ejemplo\src\pages\home\home.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Component } from '@angular/core'; | |
import { NavController } from 'ionic-angular'; | |
@Component({ | |
selector: 'page-home', | |
templateUrl: 'home.html' | |
}) | |
export class HomePage { | |
constructor(public navCtrl: NavController) { | |
} | |
takePicture(): void { | |
console.log('Tomar foto'); | |
} | |
} |
Hasta el momento solo hemos eliminado el contenido que por defecto viene con la plantilla de Ionic, hemos colocado el botón y adicionamos el método takePicture() que se va a ejecutar cuando toquemos dicho botón, por ahora solo va a imprimir el mensaje “Tomar foto” en la consola.
Podemos ver la funcionalidad implementada hasta ahora en el navegador utilizando ionic serve, pues hasta el momento no hemos utilizado ninguna funcionalidad nativa.
Volvamos a modificar el código de home.ts:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Component } from '@angular/core'; | |
// 1 | |
import { Platform } from 'ionic-angular'; | |
// 2 | |
import { DomSanitizer } from '@angular/platform-browser'; | |
// 3 | |
import { Camera, CameraOptions } from 'ionic-native'; | |
@Component({ | |
selector: 'page-home', | |
templateUrl: 'home.html' | |
}) | |
export class HomePage { | |
// 4 | |
base64Image: string; | |
// 5 | |
constructor(public platform: Platform, public domSanitizer: DomSanitizer) { | |
} | |
// 6 | |
takePicture(): void { | |
// 7 | |
this.platform.ready().then(() => { | |
// 8 | |
const options: CameraOptions = { | |
destinationType: Camera.DestinationType.DATA_URL, | |
quality: 75 | |
}; | |
// 9 | |
Camera.getPicture(options).then((imageData) => { | |
// 10 | |
this.base64Image = 'data:image/jpeg;base64,' + imageData; | |
}, (error) => { | |
// 11 | |
console.log(error); | |
}); | |
}); | |
} | |
} |
- Importamos el servicio Platform, el cual se puede utilizar para obtener información sobre la plataforma donde se está ejecutando la aplicación entre otras cosas, como ya veremos.
- Importamos el servicio DomSanitizer de Angular, veremos más adelante para qué lo utilizamos.
- Es aquí donde importamos el wrapper y clases útiles de Ionic Native para el plugin Camera, en ese caso Camera y CameraOptions.
- Propiedad donde vamos a guardar la representación de la imagen en una cadena con formato base 64.
- Inyectamos los servicios Platform y DomSanitizer.
- El método que ya habíamos adicionado para tomar la imagen.
- Utilizamos el método ready(), del servicio Platform, el cual devuelve una promesa cuando la plataforma esta disponible o no, en caso de que la plataforma sea un dispositivo, quiere decir que se puede empezar a ejecutar código nativo (como el de los plugins). A su vez, utilizamos el método then() de la promesa para especificar dos callbacks, el primero para cuando la promesa se cumpla satisfactoriamente y el segundo para cuando falla, ambos callbacks están implementados en línea (inline).
- Este paso y el siguiente se ejecutan cuando la promesa anterior se haya completado satisfactoriamente, en este paso preparamos las opciones que le queremos pasar al método que utilizaremos en el próximo paso para tomar la foto, para ello utilizamos la clase CameraOptions para especificar que la calidad de la foto es 75 (valores entre 0 y 100 son aceptados y 50 es el valor por defecto) y además, el destino, utilizando el valor Camera.DestinationType.DATA_URL lo cual quiere decir que queremos la imagen en formato base 64.
- Utilizamos el método getPicture() el cual abre la cámara del dispositivo y nos permito tomar la foto, este método recibe opciones, las cuales configuramos en el paso anterior, hay muchas más opciones que pueden revisar en la documentación. Este método también devuelve una promesa, como dijimos anteriormente acerca de los wrappers de los plugins que se encuantran en Ionic Native. Utilizamos el método then() de la promesa para especificar dos callbacks, el primero para cuando la promesa se cumpla satisfactoriamente y el segundo para cuando falla, ambos callbacks están implementados en línea (inline).
- Este es el código del callback que se ejecuta cuando la promesa retornada por getPicture() se ejecuta satisfactoriamente, el cual recibe por parámetro, en este caso imageData, la representación de la imagen en formato base 64 y se la asignamos a nuestra propiedad local base64Image, la cual definimos en el paso 4.
- Este es el código del callback que se ejecuta cuando la promesa retornada por getPicture() falla. Recibe en el parametro error el motivo por el cual falló y lo imprimimos en la consola.
Ahora volvemos a modificar el archivo home.html para adicionar el código necesario para mostrar la imagen:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<ion-header> | |
<ion-navbar> | |
<ion-title>Home</ion-title> | |
</ion-navbar> | |
</ion-header> | |
<ion-content padding> | |
<button ion-button full (click)="takePicture()">Tomar foto</button> | |
<img *ngIf="base64Image" [src]="domSanitizer.bypassSecurityTrustUrl(base64Image)"> | |
</ion-content> |
Solo hemos adicionado una línea (línea 10), una etiqueta HTML img, la cual usaremos para mostrar la imagen recien capturada por la cámara. Vemos cómo utilizamos la directiva *ngIf para sólo mostrar la imagen cuando tenga algun valor que mostrar, o sea, cuando a la propiedad base64Image se le haya asignado algun valor.
También utilizamos “one-way binding” enlace de un solo sentido para establecer el valor del atributo src de la etiqueta img; podríamos haberle asignado directamente el valor de la propiedad base64Image pero Angular por defecto “esteriliza” los valores que se le pasa a la vista para evitar problemas de seguridad, en el caso de iOS, la etiqueta img no es capaz de interpretar correctamente el valor de base64Image después de haber sido esterilizada por Angular, es por eso que utilizamos el servicio DomSanitizer en la propiedad src para deshabilitar esta funcionalidad de Angular para la propiedad base64Image, lo cual no es recomendado, sólo lo hacemos en el ámbito de este tutorial.
Para ver el resultado final tenemos que ejecutar el proyecto en un dispositivo, para ello debemos conectar el dispositivo a una PC o Mac y utilizar el comando ionic run como vimos en el post anterior y pasando la plataforma (ios o android), por ejemplo, para Android:
ionic run android
Para ejecutar ionic run hay algunos requisitos que debemos tener en cuenta, los puedes ver aquí, si tienes algun problema me dejas saber en los comentarios y veo cómo ayudarte.
Si te gustó el post ayuda a compartirlo en tus redes sociales 🙂
[…] menos algunos de los más útiles, en próximos post vamos a ver otros comandos, como por ejemplo plugin, y […]
hola te consulto. los plugins de cordova que estan en todos lados (la mayoria datan desde ionic v1 con angularjs) se pueden usar tranquilamente en un proyecto de ionic 2???
Si, recuerda que los plugins de Cordova constan de dos partes: el código nativo y la librería en Javascript con la que accedes a esas funcionalidades nativas, un proyecto en Ionic no es más que un proyecto en Javascript (Angular), entonces la forma de integrarte con un plugin cualquiera sería igual o parecida a como te integrarías con una librería de Javascript en un proyecto de Angular, en el caso de Ionic v1 sería AngularJS y en Ionic v2 sería Angular 2. A partir de Ionic 2 puedes empezar a utilizar Ionic Native, donde la gente de Ionic comenzó a implementar wrappers en TypeScript para los plugins de Cordova más utilizado, verás que cubren bastantes plugins y es la forma recomendad de utilizarlos en Ionic 2 o superior.
[…] objetivo de este post es un poco brindar una actualización al post anterios sobre cómo utilizar plugins de Cordova en Ionic 2 con Ionic Native pues algunas cosas han cambiando en la nueva versión y no quería eliminar el post anterior pues […]