Le setup pour produire une application native

Ce qui permet de produire une application native, c’est l’intégration de Capacitor à votre projet. Celle-ci est réalisée de facto lorsque vous créez votre projet Ionic.

Évidemment, comme vous souhaitez produire une application native, il faut la compiler pour chaque plateforme (iOS, android) sur laquelle vous souhaitez l’utiliser. Avant de faire cela, il faut réaliser l’opération suivante, qui vise à créer le répertoire www qui sera utilisé pour compiler en natif :

ionic build

setups spécifiques aux plateformes :

Si vous souhaitez produire des applications Android, il faut installer le package Android de Capacitor et indiquer à votre projet que vous allez l’utiliser :

npm install @capacitor/android
npx cap add android

Si vous souhaitez produire des applications iOS, il faut installer le package Android de Capacitor et indiquer à votre projet que vous allez l’utiliser :

npm install @capacitor/ios
npx cap add ios

Attention

Pour compiler pour iOS, vous avez besoin d’être sur un OS Apple et d’avoir à disposition XCode.

Production de l'application native

Essentiellement, la production de l’application native se fait en 3 étapes :

  1. Compiler l’application web en exécutant la commande bash :

    ionic build
    
  2. Synchroniser avec l’appli native en exécutant la commande bash :

    npx cap copy
    
  3. Ouvrir Android studio ou XCode :

    npx cap open android
    

    Attention

    Pour pouvoir utiliser cette commande, il faut préciser à la ligne de commande le « path » d’android-studio :

    export CAPACITOR_ANDROID_STUDIO_PATH=`which android-studio`
    

    Pour Xcode, il faut utiliser plutôt :

    npx cap open ios
    

    Le résultat obtenu avec Android studio :

    Le rendu de l'application sur un smartphone

Création d'une Progressive Web Application (PWA)

Pour transformer votre application en PWA, il faut installer le package suivant :

ng add @angular/pwa

Cela va créer, notamment, deux fichiers : un web manifest (le manifest du PWA) et un fichier de configuration pour ngsw (qui va gérer le cache du service worker).

Les fichiers après avoir installé @angular/pwa

Notez que l’on a toujours le répertoire www et c’est dans celui-ci que l’on va produire notre PWA. Pour cela, il faut utiliser la commande suivante :

ionic build --prod -- --base-href "/xmobile_cours/maPWA/"

Ici, /xmobile_cours/maPWA/ est l’URL à partir de laquelle on accède à la PWA à partir d’un navigateur, comme indiqué ci-dessous :

La PWA dans un navigateur

Notez également dans la commande ionic build que, juste après le –prod, il y a un . Celui-ci sert à indiquer que ce qui suit sont des paramètres à passer à Angular plutôt qu’à Ionic.

Attention

Dans le –base-href, il est important de mettre un / à la fin de l’URL.

Dans l’image ci-dessus, on a ouvert les developer tools et, contrairement à d’habitude, ce qui nous intéresse n’est pas la console ou le network mais plutôt l’onglet application. On y voit qu’un service worker est associé à notre page, ce qui prouve bien qu’il s’agit d’une PWA.

Installation d'une PWA

Pour permettre d’installer aisément la PWA, on va créer un bouton d’installation. Le HTML est classique : on crée un bouton standard et on associe à son événement click une callback :

home.page.html
<ion-header [translucent]="true">
  <ion-toolbar>
    <ion-buttons slot="start">
      <ion-button *ngIf="promptEvent" (click)="onInstall()">Installer</ion-button>
    </ion-buttons>
    <ion-title>Blank</ion-title>
    <ion-buttons slot="end">
      <ion-button (click)="openMenu($event)">
        <ion-icon slot="icon-only"
                  name="add-circle"></ion-icon>
      </ion-button>
    </ion-buttons>
  </ion-toolbar>
</ion-header>

<ion-content [fullscreen]="true">
  <p><a routerLink="/cours">vers la page cours</a></p>
</ion-content>

Notez le *ngIf=promptEvent : l’idée est d’avoir dans le TypeScript un attribut qui permet de déterminer si l’on a installé ou non l’application. Pour cela, ce TypeScript va exploiter l’événement beforeinstallprompt. Quand on démarre notre application, cet événement est émis si et seulement si on n’a pas encore installé l’application. Dans ce cas, on va s’arranger pour que promptEvent ne soit pas null. Ainsi, le bouton d’installation sera visible. Lorsque l’application a été installée, l’événement beforeinstallprompt ne sera pas émis et notre bouton d’installation ne sera pas visible.

home.page.ts
import { Component, OnInit } from '@angular/core';
import {
  IonHeader, IonToolbar, IonTitle, IonContent,
  IonList, IonItem,
  IonButtons, IonMenuButton, IonButton, IonIcon, PopoverController
} from '@ionic/angular/standalone';
import {MonServiceService, MyInfo} from "../mon-service.service";
import {RouterLink} from "@angular/router";
import {DropdownMenuComponent} from "../dropdown-menu/dropdown-menu.component";
import {addIcons} from "ionicons";
import {addCircle} from "ionicons/icons";
import {CommonModule} from "@angular/common";

@Component({
  selector: 'app-home',
  templateUrl: 'home.page.html',
  styleUrls: ['home.page.scss'],
  standalone: true,
  imports: [
    IonHeader, IonToolbar, IonTitle, IonContent,
    IonItem, IonList,
    RouterLink, IonButtons, IonMenuButton, IonButton, IonIcon,
    CommonModule
  ],
})
export class HomePage implements OnInit {
  info!: MyInfo;

  // un événement qui sera initialisé dans le constructeur si l'application n'a pas
  // été installée
  promptEvent: any = null;

  constructor(private mon_service: MonServiceService,
              private popover: PopoverController) {
    // l'événement ""beforeinstallprompt" est émis chaque fois que l'on charge la
    // page et que l'application n'a pas encore été installée. S'il est émis, on
    // met à jour promptEvent
    window.addEventListener(
      'beforeinstallprompt', event => {
        this.promptEvent = event;
      });
  }

  async onInstall() {
    if (this.promptEvent !== null) {
      this.promptEvent.prompt();
      const { outcome } = await this.promptEvent.userChoice;
      if (outcome === 'accepted') {
        this.promptEvent = null;
      }
    }
  }

  async ngOnInit() {
    this.mon_service.getInfos().subscribe(res => {this.info = res;});

    addIcons({addCircle});
  }

  openMenu(myevent: MouseEvent) : void {
    // on crée le popup contenant le code du menu
    this.popover.create({
      component: DropdownMenuComponent, // on précise quoi inclure
      showBackdrop: true,
      cssClass: 'my-menu-class', // on peut préciser un css
      event: myevent,            // l'événement clic souris
      componentProps: { // ici, on indique les propriétés que l'on souhaite
        myprop: 'xxxx'  // initialiser dans le composant DropdownMenuComponent
      }
    }).then((popoverElement) => {
      popoverElement.present(); // on affiche le menu
      popoverElement.onDidDismiss().then((res) => {
        console.log(res);
      });
    });
  }
}

Avec le code ci-dessus, lorsque l’application n’est pas installée, on obtient l’affichage suivant :

Le bouton d'installation de la PWA

Lorsque l’on clique sur le bouton :

Lorsque l'on clique sur le bouton d'installation de la PWA

Après avoir cliqué sur install, l’application est installée. On peut la voir ici en allant sur l’URL chrome://apps :

L'application installée dans apps

Si l’on clique sur l’icône, cela démarre notre application. On peut voir tout en haut de la fenêtre qu’il s’agit bien d’une application et non plus simplement d’une page web. On remarque, d’ailleurs, qu’on ne peut plus saisir d’URL.

L'application installée dans apps
 
© C.G. 2007 - 2024