Skip to content
Aprende a hacer apps móviles con Ionic 2 

Ionic Native… ¿en el navegador?

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:

ionic get picture example

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:

ionic error cordova not available on browser

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:

  1. Creas una clase que extiende la clase de ionic-native que quieres reemplazar
  2. 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).

ionic native camera browser mock

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!

Published inAngular 2Ionic 3

3 Comments

  1. 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!

  2. 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!

    • Enrique Oriol Enrique Oriol

      ¡Gracias!

Deja un comentario