Comment accéder à la bibliothèque et à la caméra dans Ionic ?
Toutes les étapes que nous allons voir dans ce tuto Ionic 4

Aujourd’hui nous allons voir comment utiliser le plugin Camera dans Ionic. Il permet d’accéder à la bibliothèque photo et vidéo de l’utilisateur et d’utiliser la caméra de l’appareil.

Nous verrons également ensuite comment exporter cette photo dans l’espace de stockage de Firebase.

Voilà les étapes que nous allons suivre dans ce tutoriel:

  1. Présentation du plugin Ionic Camera
  2. Comment installer le plugin
  3. Ouvrir la bibliothèque photo et vidéo
  4. Ouvrir l’appareil photo avec la caméra
  5. Envoyer cette image dans Firebase

Que permet de faire le plugin Ionic Camera ?

Créer une application comme Snapchat est possible avec le plugin Ionic Camera

La possibilité de partager des photos et d’accéder à la caméra de nos smartphones sont devenus les fonctionnalités parmi les plus utilisées dans nos applications.

Qu’il s’agisse de Facebook, Snapchat ou encore Instagram pour ne citer que les plus célèbres applications, le plugin camera vous permettra de créer toutes sortes de fonctionnalités.

Voilà les principales fonctionnalités du plugin Ionic Camera:

  • Prendre des photos avec la caméra de l’appareil
  • Accéder aux photos et vidéos de l’utilisateur
  • Envoyer ces photos dans Firebase
  • Partager ces photos avec ces contacts

Tout ce qui concerne le partage ou l’envoi de ces photos dans Firebase n’est pas géré uniquement avec le plugin Ionic Camera. Mais nous verrons dans ce tutoriel que le plugin nous facilite les choses.

Comment installer le plugin Ionic Camera dans votre application ?

Pour commencer le tutoriel, nous allons voir comment installer le plugin Ionic Camera. Vous allez voir que son installation est classique est reste la partie la plus simple de ce tuto Ionic 4.

Je vous donne également accès à tous les liens importants de la documentation dont vous pourriez avoir besoin, à commencer par celle d’Ionic: https://ionicframework.com/docs/native/camera

Ensuite je vous partage le lien de la documentation de cordova directement sur GitHub qui est de loin celle qui est la plus fournie, mais facile à prendre en main pour les débutants: https://github.com/apache/cordova-plugin-camera

On enchaîne ensuite avec les deux commandes à entrer dans le terminal de votre application pour installer le plugin.

Comme pour tous les plugins Cordova, vous avez une commande ionic à entrer pour installer le plugin Cordova et une commande NPM pour installer le plugin natif.

Voilà donc les deux commandes, n’oubliez d’ajouter sudo devant npm si vous êtes sur Mac:

ionic cordova plugin add cordova-plugin-camera
npm install @ionic-native/camera

Une fois l’installation du plugin terminée, nous allons le déclarer dans notre application pour pouvoir l’utiliser dans nos différentes pages.

Rendez-vous dans votre fichier src/app/app.module.ts et importer le plugin Camera comme ci-dessous:

import { Camera } from '@ionic-native/camera/ngx';

Ensuite, nous devons déclarer ce plugin dans notre providers, comme ceci:

providers: [
  StatusBar,
  SplashScreen,
  Camera,
  { provide: RouteReuseStrategy, useClass: IonicRouteStrategy }
]

Maintenant que le plugin est déclaré dans notre application, nous pouvons l’importer dans une page précise, par exemple dans mon cas la page src/app/home/home.page.ts:

import { Camera, CameraOptions } from '@ionic-native/camera/ngx';

N’oubliez pas également de déclarer le plugin dans votre constructor() pour pouvoir l’utiliser dans le reste de votre page:

constructor(
    private camera: Camera
) { }

C’est tout pour la parti importation du plugin dans notre application. Mais n’oubliez pas que pour la dernière partie du tuto (envoyer image dans Firebase) nous aurons besoin du plugin AngularFire qui devrait être également installé et configuré.

Comment ouvrir la bibliothèque Photo et Vidéo de l’utilisateur ?

La fonctionnalité la plus simple du plugin Camera est l’accès à la bibliothèque photo de l’utilisateur.

Nous allons donc commencer par proposer à l’utilisateur d’ouvrir sa bibliothèque, de sélectionner une photo et de la lui afficher sur notre page.

Voilà les quelques étapes à suivre:

  • Créer le bouton HTML
  • Coder la fonction d’accès à la bibliothèque
  • Stocker l’image dans une variable
  • Afficher cette image dans le HTML

Comme prévu, nous créons tout d’abord un bouton HTML avec la balise ion-button classique d’Ionic. Nous associons surtout ce bouton à la fonction addPhoto():

<ion-button (click)="addPhoto()" color="tertiary" expand="block">
  <ion-icon name="image" slot="start"></ion-icon>
  Ouvrir la bibliothèque
</ion-button>

En dessous de ce bouton, nous proposons l’affichage d’une image dont la source est stockée dans la variable image. Nous incluons cette image dans deux boîtes avec des classes que nous allons déclarer pour centrer cette image.

<div class="flex">
  <div class="img-box">
    <img [src]="image">
  </div>
</div>

Voilà les quelques propriétés CSS que vous pouvez ajouter à vos trois éléments:

.flex {
  margin-top: 10px;
  display: flex;
  justify-content: center;
}
.img-box {
  height: 200px;
  overflow: hidden;
}
img {
  height: 200px;
}

Nous créons également la variable image qui est une chaîne de caractère contenu la source de l’image. Par défaut je lui donne l’URL d’une image grise avec une icône:

image = 'https://www.kasterencultuur.nl/editor/placeholder.jpg';

Venons-en enfin à la fonction associée à notre bouton HTML addPhoto(), qui permet d’un seul coup d’accéder à la bibliothèque et d’afficher l’image sélectionnée:

async addPhoto() {
    const libraryImage = await this.openLibrary();
    this.image = 'data:image/jpg;base64,' + libraryImage;
}

Vous remarquerez que notre fonction fait tout d’abord appel à une autre fonction que nous avons appelé openLibrary(). Comme son nom l’indique elle va ouvrir la bibliothèque de l’utilisateur, mais surtout nous retourner le fichier de cette image:

async openLibrary() {
  const options: CameraOptions = {
    quality: 100,
    destinationType: this.camera.DestinationType.DATA_URL,
    encodingType: this.camera.EncodingType.JPEG,
    mediaType: this.camera.MediaType.PICTURE,
    targetWidth: 1000,
    targetHeight: 1000,
    sourceType: this.camera.PictureSourceType.PHOTOLIBRARY
  };
  return await this.camera.getPicture(options);
}

C’est cette fonction openLibrary() qui utilise vraiment le plugin Camera et qui utilise plusieurs paramètres comme:

  • La qualité de l’image
  • Le type de média (photo ou vidéo) ou encore
  • L’origine de celle-ci (bibliothèque ou caméra)

Si on reprend la fonction addPhoto() associée à notre bouton HTML, elle va s’exécuter en quatre temps:

  • On ouvre la bibliothèque photo de l’utilisateur
  • Il sélectionne l’une d’entre elle
  • On affecte à la variable image le contenu de cette photo
  • La photo s’affiche dans le HTML

ATTENTION: Pour tester le fonctionnement de votre fonction, vous devez la tester sur la plateforme Browser en lançant la commande suivante:

ionic cordova run browser

Comment ouvrir la caméra et prendre une photo ?

Passons maintenant à la partie accès à la caméra et à l’appareil photo. En fait, le principe est le même que pour l’accès à la bibliothèque, nous devons simplement changer un paramètre dans notre fonction qui utilise le plugin Camera.

Nous devons modifier le paramètre source de notre objet CameraOptions comme ceci:

sourceType: this.camera.PictureSourceType.CAMERA

Je pourrais créer deux fonctions séparer, mais comme elle utiliseront quand même une technique identique, je vais reprendre la fonction addPhoto() mais lui ajouter un paramètre.

Vous pouvez donc créer un bouton supplémentaire qui sera associé également à la fonction addPhoto(), mais avec le paramètre ‘camera‘.

Le premier bouton pour accéder à la bibliothèque sera lui toujours associé à la fonction addPhoto(), mais avec le paramètre ‘library‘. Voilà le résultat de nos deux boutons HTML:

<ion-button (click)="addPhoto('library')" color="tertiary" expand="block">
  <ion-icon name="image" slot="start"></ion-icon>
  Ouvrir la bibliothèque
</ion-button>

<ion-button (click)="addPhoto('camera')" color="secondary" expand="block">
  <ion-icon name="camera" slot="start"></ion-icon>
  Prendre une photo
</ion-button>

On passe du coup à notre fameuse fonction addPhoto() qui permettra d’exécuter deux codes différents selon si on a transmis le paramètre ‘camera’ ou ‘library’.

async addPhoto(source: string) {
  if (source === 'camera') {
    console.log('camera');
    const cameraPhoto = await this.openCamera();
    this.image = 'data:image/jpg;base64,' + cameraPhoto;
  } else {
    console.log('library');
    const libraryImage = await this.openLibrary();
    this.image = 'data:image/jpg;base64,' + libraryImage;
  }
}

Selon chaque cas, on va ensuite exécuter cette fois-ci deux fonctions bien différentes, openCamera() et openLibrary().

On stockera dans les deux cas le résultat de cette fonction dans des constantes, cameraPhoto ou libraryImage que nous affecterons finalement à la variable image pour l’afficher dans le HTML.

Examinons maintenant la nouvelle fonction openCamera(), qui est très similaire à la fonction openLibrary() à l’exception du paramètre source qui cette fois contient la valeur CAMERA:

async openCamera() {
  const options: CameraOptions = {
    quality: 100,
    destinationType: this.camera.DestinationType.DATA_URL,
    encodingType: this.camera.EncodingType.JPEG,
    mediaType: this.camera.MediaType.PICTURE,
    targetWidth: 1000,
    targetHeight: 1000,
    sourceType: this.camera.PictureSourceType.CAMERA
  };
  return await this.camera.getPicture(options);
}

Pour tester le fonctionnement de cette fonctionnalité sur votre ordinateur, vous pouvez lancer la version Browser de votre application avec la commande:

ionic cordova run browser

Personnellement j’ai testé son fonctionnement directement sur mon iPhone et la fonction me permet bien de prendre une photo.

ATTENTION: Les simulateurs d’iPhone de Xcode ne permettent pas d’ouvrir la caméra, nous ne pouvez accéder que à la bibliothèque photo.

Comment envoyer cette image dans la base de stockage de Firebase ?

Dans cette partie nous allons voir comment envoyer cette photo ou image dans notre espace de stockage de Firebase.

Vous devez avoir un projet Firebase déjà associé à notre application Ionic. Si ce n’est pas le cas, vous pouvez suivre ce tutoriel: https://drissas.com/associer-firebase-application-ionic-4/

Nous allons utiliser plus précisément le plugin AngularFireStorage pour envoyer notre image dans Firebase.

Vous devez l’avoir importé dans votre fichier src/app/app.module.ts comme ceci:

import { AngularFireStorageModule } from '@angular/fire/storage';

Vous devez également le déclarer dans le tableau imports comme ceci:

imports: [
    BrowserModule,
    IonicModule.forRoot(),
    AppRoutingModule,
    AngularFireModule.initializeApp(firebaseConfig),
    AngularFireStorageModule,
],

Nous pouvons maintenant retourner dans notre page Home et plus précisément dans notre fichier src/app/home/home.page.ts pour importer le plugin AngularFireStorage:

import { AngularFireStorage } from '@angular/fire/storage';

Je vous propose également d’importer deux plugins natifs d’Angular et Ionic, pour afficher un Chargement et une Alerte lors de l’envoi de notre image:

import { LoadingController, AlertController } from '@ionic/angular';

Vous pouvez désormais AngularFireStorage tous votre plugins dans votre constructor() pour pouvoir les utiliser dans notre futur fonction:

constructor(
    public loadingController: LoadingController,
    public alertController: AlertController,
    public afSG: AngularFireStorage,
    private camera: Camera
  ) {}

Nous déclarons également deux variable supplémentaires pour l’envoi de notre image dans Firebase:

  • imagePath contiendra l’adresse de notre image dans la base de stockage Firebase (qui sera unique avec la date du jour)
  • upload stockera l’avancement de l’envoi de l’image dans Firebase pour afficher ou masquer notre chargement.

Voilà donc les trois variables dont vous avez besoin dans votre page Home:

export class HomePage {
  image = 'https://www.kasterencultuur.nl/editor/placeholder.jpg';
  imagePath: string;
  upload: any;

Je passe maintenant à la création de mon bouton HTML pour envoyer la photo dans Firebase. Je place ce bouton en dessous de mon image et je l’associe à la fonction uploadFirebase():

<ion-button (click)="uploadFirebase()" color="warning"  expand="block">
  <ion-icon name="cloud-upload" slot="start"></ion-icon>
  Envoyer la photo
</ion-button>

Dans cette fonction uploadFirebase(), je vais avoir besoin de plusieurs éléments, notamment donner un valeur à ma variable imagePath:

this.imagePath = new Date().getTime() + '.jpg';

En fait je donne à la variable imagePath la valeur de la date absolue du moment où on clique sur le bouton, suivi du caractère ‘.jpg’ ce qui donnera à l’image l’adresse ‘1568984479937.jpg’ par exemple.

Si j’avais voulu mettre mon image dans un dossier et même un sous-dossier, j’aurais simplement dû à ajouter le nom du dossier avant:

this.imagePath = 'monDossier/' + new Date().getTime() + '.jpg';

Maintenant que j’ai donné une adresse de stockage Firebase à mon image, je peux passer à l’upload dans Firebase, et pour ça rien de plus simple.

On utilise le plugin AngularFireStorage et sa fonction putString() pour placer un fichier (ici une image) à une adresse bien précise grâce à l’autre fonction ref():

this.upload = this.afSG.ref(this.imagePath).putString(this.image, 'data_url');

Voilà donc notre fonction uploadFirebase() pour le moment:

uploadFirebase() {
  this.imagePath = new Date().getTime() + '.jpg';
  this.upload = this.afSG.ref(this.imagePath).putString(this.image, 'data_url');
  this.image = 'https://www.kasterencultuur.nl/editor/placeholder.jpg';
}

Nous pourrions nous arrêter là, le problème c’est que nous ne sommes pas capable de suivre la progression de l’upload dans Firebase.

C’est pour cette raison que je vous ai proposé d’importer les Controller des Alert et des Loader. Pour en savoir plus sur ces éléments consultez la documentation d’Ionic:

Ainsi lorsqu’on clique sur le bouton HTML, on ouvre un chargement qui ne s’arrête que lorsque l’upload dans Firebase est terminé.

async uploadFirebase() {
	const loading = await this.loadingController.create();
	await loading.present();
	this.upload = this.afSG.ref(this.imagePath).putString(this.image, 'data_url');
	this.upload.then(async () => {
		await loading.onDidDismiss();
		this.image = 'https://www.kasterencultuur.nl/editor/placeholder.jpg';
	});
}

J’ai aussi ajouté un message d’alerte lorsque l’upload est terminé, pour bien montré que l’envoi dans la base à fonctionné:

async uploadFirebase() {
	const loading = await this.loadingController.create({
		duration: 2000
	});
	await loading.present();
	this.upload = this.afSG.ref(this.imagePath).putString(this.image, 'data_url');
	this.upload.then(async () => {
		await loading.onDidDismiss();
		this.image = 'https://www.kasterencultuur.nl/editor/placeholder.jpg';
		const alert = await this.alertController.create({
			header: 'Félicitation',
			message: 'L\'envoi de la photo dans Firebase est terminé!',
			buttons: ['OK']
		});
		await alert.present();
	});
}

Voilà notre fonction d’envoi d’une image dans Firebase est terminé mais il nous reste deux éléments pour que l’upload fonctionne.

ATTENTION: Vous devez activer la base de stockage dans l’onglet Storage de votre projet Firebase pour que cela fonctionne.

Une fois que votre base de stockage est crée, vous devez vous rendre dans l’onglet ‘Règles‘ et modifier les conditions d’accès à la base.

Par défaut les utilisateurs doivent être connecté pour pouvoir envoyer des fichiers dans la base, vous pouvez enlever cette condition pour vos tests:

allow read, write;

Voilà par exemple les règle de mon projet Firebase:

Les règles d’accès de la base de stockage de mon projet Firebase

ATTENTION: Dernière chose à faire absolument, tant que vous n’avez pas activé votre base de stockage dans Firebase il vous manquera le paramètre storageBucket parmi vos codes de configuration.

N’oubliez pas de mettre à jour votre constante firebaseConfig dans votre fichier src/app/app.module.ts pour lui ajouter le champ storageBucket:

export const firebaseConfig = {
  apiKey: '************************************-EjQ',
  authDomain: 'camera-******.firebaseapp.com',
  databaseURL: 'https://camera-******.firebaseio.com',
  projectId: 'camera-******',
  storageBucket: 'camera-******.appspot.com',
  messagingSenderId: '************',
  appId: '1:************:web:************'
};

Téléchargez le code source de l’application Ionic

C’est la fin de ce tuto Ionic 4, merci de l’avoir consulté! Je vous laisse comme d’habitude le code source de cette application, notamment le fichier HTML et surtout TypeScript de ma page Home.

Vous pouvez télécharger le code source en cliquant ICI ou sur l’image juste en dessous: