Please or Register to create posts and topics.

Ionic/Angular: How to exit application on pressing hardware back button

The tutorial explains how to override standard hardware back button behaviour by custom logic. The article contains detailed descriptions of three most common scenarios of hardware back button use.

1. Basic scenario: Exit application on pressing hardware back button

Create back-button service in the application using the following Ionic command:

ionic g service services/back-button

Add the following code to back-button.service.ts and app.component.ts files. The code creates a custom service called BackButtonService and initialize it once in AppComponent by calling init() method. In the init method I registered hardware back button callback fired when uses presses the back button on the android phone. Then I call navigator['app'].exitApp() for exit the application.



import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
import { Platform, NavController} from '@ionic/angular';

@Injectable({
  providedIn: 'root'
})
export class BackButtonService {
  init() {
    this.platform.backButton.subscribeWithPriority(10, async () => {
      const currentUrl = this.router.url;
      if (currentUrl === "/home") {
        navigator['app'].exitApp();;
      } else {
        this.navControlelr.back();
      }

    });
  }


  constructor(private platform: Platform,
    private router: Router,
    private navControlelr: NavController) { }
}

import { Component } from '@angular/core';

import { Platform } from '@ionic/angular';
import { SplashScreen } from '@ionic-native/splash-screen/ngx';
import { StatusBar } from '@ionic-native/status-bar/ngx';
import { BackButtonService } from './services/back-button.service';

@Component({
  selector: 'app-root',
  templateUrl: 'app.component.html',
  styleUrls: ['app.component.scss']
})
export class AppComponent {
  constructor(
    private platform: Platform,
    private splashScreen: SplashScreen,
    private statusBar: StatusBar,
    private backButtonService: BackButtonService
  ) {
    this.initializeApp();
  }

  initializeApp() {
    this.platform.ready().then(() => {
      this.statusBar.styleDefault();
      this.splashScreen.hide();
      this.backButtonService.init();
    });
  }
}

2. Extended scenario: Exit an application on pressing hardware back button with confirmation popup

To implement the following scenario I created the withAlert method responsible for displaying popup and invoking passed action in case on tam on OK button. Then I replaced the 13th ile from the previous example("navigator['app'].exitApp();") by invocation of newly created method.



import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
import { AlertController, NavController, Platform} from '@ionic/angular';

@Injectable({
  providedIn: 'root'
})
export class BackButtonService {
  private lastTimeBackButtonWasPressed = 0;
  private timePeriodToAction = 2000;

  init() {
    this.platform.backButton.subscribeWithPriority(10, async () => {
      const currentUrl = this.router.url;
      if (currentUrl === "/home") {
        this.withAlert("Do you really want to exit?", () => {
          navigator['app'].exitApp();
        });
      } else {
        this.navControlelr.back();
      }

    });
  }

  async withAlert(message: string, action: () => void) {
    const alert = await this.alertController.create({
      message: message,
      buttons: [{
        text: "Cancel",
        role: "cancel"
      },
      {
        text: "OK",
        handler: action
      }]
    });

    await alert.present();
  }

  constructor(private platform: Platform,
    private router: Router,
    private navControlelr: NavController,
    private alertController: AlertController) { }
}

3. Advanced scenario: Exit an application on pressing hardware back button twice within 2 seconds

In the last example I created the withDoublePress method analogically to the withAlert method, but in this case I put some logic to calculate if the hardware back butt was pressed twice within 2000 milliseconds.



import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
import { AlertController, NavController, Platform, ToastController } from '@ionic/angular';

@Injectable({
  providedIn: 'root'
})
export class BackButtonService {
  private lastTimeBackButtonWasPressed = 0;
  private timePeriodToAction = 2000;

  init() {
    this.platform.backButton.subscribeWithPriority(10, async () => {
      const currentUrl = this.router.url;
      if (currentUrl === "/home") {
        this.withDoublePress("Press again to exit", () => {
          navigator['app'].exitApp();
        });
      } else {
        this.navControlelr.back();
      }

    });
  }

  async withDoublePress(message: string, action: () => void) {
    const currentTime = new Date().getTime();

    if (currentTime - this.lastTimeBackButtonWasPressed < this.timePeriodToAction) {
      action();
    } else {
      const toast = await this.toastController.create({
        message: message,
        duration: this.timePeriodToAction
      });

      await toast.present();

      this.lastTimeBackButtonWasPressed = currentTime;
    }
  }

  async withAlert(message: string, action: () => void) {
    const alert = await this.alertController.create({
      message: message,
      buttons: [{
        text: "Cancel",
        role: "cancel"
      },
      {
        text: "OK",
        handler: action
      }]
    });

    await alert.present();
  }

  constructor(private platform: Platform,
    private router: Router,
    private navControlelr: NavController,
    private alertController: AlertController,
    private toastController: ToastController) { }
}

Watch the tutorial in YouTube