Ionic Native es genial: Más de 130 plugins nativos para Android, iOS y compañía, para exprimir al máximo las SDKs nativas y potenciar tu app con herramientas de geolocalización, cámara, NFC, etc.
Pero tiene un problema (sobretodo para PWA). Al ser plugins nativos, solo funcionan en apps móviles, pero no en navegador…
¡Hasta ahora!
Ionic Native 3+ te permite mockear los plugins nativos para poderlos usar desde el navegador.
Eso te facilita poder lanzar una PWA y una app real con las mismas funcionalidades, siempre y cuando el navegador disponga de una API alternativa al plugin (piensa en la cámara, por ejemplo).
Ionic Native 3+ te permite mockear los plugins nativos para poderlos usar desde el navegador.
Si tu app necesita acceder a APIs que solo están disponibles en nativo, puedes generar datos de test para el navegador. ¡Aunque tu app necesite una API nativa, puedes llevar a cabo todo el desarrollo en navegador, sin necesidad de hacer deploys constantes al simulador!
Lo sé, estás de subidón, pero piensas… ¿y como lo hago?
¡Pues aquí estoy yo para echarte una mano!
Mockeando un plugin
Voy a enseñarte como hacer un mock básico con el plugin de la cámara que te permita desarrollar sin problemas en navegador.
1 – Instalando el plugin de cámara
Lo primero es asegurarte de que dispones de la última versión de @ionic-native/core
, por que la CLI trae una por defecto, pero si no está actualizada te encontrarás con problemas:
npm install --save @ionic-native/core@latest
Hecho esto, instala el paquete y el plugin:
ionic plugin add --save cordova-plugin-camera
npm install --save @ionic-native/camera
2 – Incorporar el plugin al módulo principal
Abre src/app/app.module.ts y añade el import del plugin.
// src/app/app.module.ts
//...some imports...
import { Camera } from '@ionic-native/camera';
@NgModule({
//...some stuff...
providers: [
Camera,//this is only for native approach
//...some stuff...
]
})
export class AppModule {}
3 – Utiliza el plugin
He creado una vista muy simple con un botón de «hacer foto» y que muestra el resultado debajo. Lo puedes ver a continuación:
Además de algo de estilo, el código es el siguiente (he partido de la plantilla blank de ionic 3):
src/pages/home/home.html
<!-- src/pages/home/home.html -->
<!-- header stuff -->
<ion-content padding>
<div class="container">
<button ion-button icon-only large round (click)="takeImage()">
<ion-icon name="camera"></ion-icon>
</button>
<img *ngIf="image" [src]="image">
</div>
</ion-content>
src/pages/home/home.ts
// src/pages/home/home.ts
import { Component } from '@angular/core';
import { Camera } from "@ionic-native/camera";
@Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
image:any = null;
constructor(public camera: Camera) {
}
takeImage(){
this.camera.getPicture().then(img =>{
this.image = img;
})
}
}
Como ves, al tocar el botón se llama al método takeImage()
del componente, que acaba llamando a this.camera.getPicture()
4 – Ejecución
Por desgracia, el problema de lo que has visto hasta ahora es que esta llamada solo funciona si estás en dispositivo (o simulador), pero no en web.
Si intentas usarlo en web, al clickar el botón obtienes este resultado:
Pero, PERO… ¡TRANQUI! justamente eso es lo que te voy a enseñar a evitar 🙂
5 – Crear un mock de la cámara
Lo más simple en este caso es hacer un mock que devuelva una imagen estática al usar el método que llama a la cámara.
Para eso, puedes crear un nuevo archivo y añadir el contenido que ves a continuación (yo lo he llamado camera.mock.ts y lo he metido en una nueva carpeta).
src/plugins-mock/camera.mock.ts:
//src/plugins-mock/camera.mock.ts
import { Camera } from '@ionic-native/camera';
export class CameraMock extends Camera {
getPicture(options) {
return new Promise((resolve, reject) => {
resolve(this.fakeImage);
})
}
fakeImage = "imageCodifiedInBase64";
}
Como ves, el procedimiento es muy sencillo:
- Creas una clase que extiende la clase de ionic-native que quieres reemplazar
- Sobreescribes el método que necesitas usar, de modo que no haga uso del plugin nativo (en este caso he sobreescrito el método
getPicture
).
6 – Incorporar el plugin al módulo principal
Tienes que reemplazar el provider de la cámara que tenías antes y usar el nuevo mock como clase del provider. Así:
src/app/app.module.ts
// src/app/app.module.ts
//...some imports...
import { Camera } from '@ionic-native/camera';
import { CameraMock } from '../plugin-mocks/camera.mock';
@NgModule({
//...some stuff...
providers: [
{provide: Camera, useClass: CameraMock},
//...some stuff...
]
})
export class AppModule {}
7 – Ejecución en browser
Ahora sí, como puedes ver si lo lanzas en web y le das al botón, te aparece el gatito (en fakeImage
he hardcodeado esa imagen en base 64).
Te dejo enlace al repositorio con el ejemplo completo.
Reemplazando la funcionalidad en browser
Lo que has visto arriba está bien para desarrollo, te permite ver el resultado sin necesidad de ejecutar en dispositivo, pero lo realmente potente sería reemplazar el plugin por código que supliera la misma funcionalidad en navegador.
Hay otros plugins que serían más fáciles de replicar. En este caso concreto, HTML5 dispone de unas APIs para utilizar la cámara (cámara del smartphone o webcam en el ordenador), aunque no están aún muy estandarizadas. Además, deberías tomar decisiones sobre como muestras la vista previa y demás. Vamos, que no es trivial.
Aún así, la verdad es que me pica la curiosidad… dejo abierta la implementación de esta solución para un futuro post 🙂 ¿Te gustaría?
¡Un Abrazo!
Buena Enrique:
Buena alternativa… ahora en Ionic3 al ser los plugins nativos implementados como providers, podemos extenderlos como comentas en el POST.
Nosotros (http://www.fecron.com) en nuestros desarrollos en Ionic2, lo que hacíamos (para obtener esta funcionalidad que comentas en el POST) era siempre crear un provider para la funcionalidad deseada (Camera, Facebook, GooglePlus, Geo, etc) que es la que usamos desde los componentes, por ejemplo CamaraProvider, y dentro de éste comprobar si estamos bajo plataforma con las herramientas que nos ofrece Ionic.
Dentro de este nuevo CamaraProvider, si estamos en plataforma (nativo), hacíamos uso del provider Camera (provider nativo) y si no, hacíamos uso de provider CameraWeb (provider que nosotros hemos implementado, o funciones en el propio CamaraProvider para emular el comportamiento de Camera).
De esta forma:
-Si se cambia algo en los plugins nativos no debemos tocar los componentes
-Conseguimos centralizar el código de la funcionalidad en un provider (CameraProvider).
-Si en el futuro IonicX incluye algo nuevo para un determinado plugin nativo, la migración se hace trivial como nos ha sucedido en este caso al migrar de Ionic2 a Ionic3
Ahora como el tratamiento es como provider para los plugins en Ionic3 se puede construir todo más al estándar de Angular, con lo que en el módulo nuestro variaría a:
//…some stuff…
providers: [
{provide: Camera, useClass: CameraProvider},
//…some stuff…
Y hacer uso siempre de Camera en los componentes.
Gracias por la anotación, es un detalle muy a tener en cuenta a la hora de diseñar nuestras aplicaciones y una nueva incorporación en Ionic que se esperaba desde hace tiempo.
Dejo un POST con otra alternativa en Ionic2 si se desea Mockear donde se habla del tema de la Camera:
https://geykel.com/2017/02/22/como-utilizar-plugins-de-cordova-en-ionic-2-con-ionic-native/
Para Ionic2 con incluir la imagen cuando falla se podría mockear (la camara podría fallar otros motivos) de forma muy sencilla:
Camera.getPicture(options).then((imageData) => {
// 10
this.base64Image = ‘data:image/jpeg;base64,’ + imageData;
}, (error) => {
// 11
console.log(error); //AQUI MOCK
});
Un abrazo y enhorabuena por tu POST!
Hola, llevo poco en esto de Ionic y estoy haciendo mis primeras aplicaciones…
Me ha gustado mucho la entrada y a su vez también la respuesta de David.
Saludos!
¡Gracias!
Una pregunta…como se puede hacer para que en vez de poder sacar solo 1 foto puedas sacar varias?, en tu curso tienes algún ejemplo con varias fotos? o sabes de alguna url para esto?, e todas formas tengo pensado coger si o si tu curso, que lo veo muy interesante 🙂
Voy a probar ahora mismo lo que comentas, no había localizado tu página hasta ahora je, pero esto que comentas es muy interesante porque es mucho más agil ver todo en el navegador.
Gracias y felicidades por tu post.
Yo estoy haciendo un lector de QR con ionic. Al generar el apk funciona perfectamente. Al ejecutar ionic cordova run browser , me genera el contenido en www. Copio esa carpeta www a mi servidor y me da error de cordova.
No encuentro la forma de crear una pwa lector de qr con ionic.
¿Alguien tiene la solución?