11
votes

I am working in my Ionic 4 app and When the user clicks 2 times on the mobile back button, then it should close the app but this is not happening.

This is my app.component.ts:

lastTimeBackPress = 0;
timePeriodToExit = 2000;
@ViewChildren(IonRouterOutlet) routerOutlets: QueryList<IonRouterOutlet>;

constructor(){
this.backButtonEvent();
}

backButtonEvent() {
    document.addEventListener("backbutton", () => { 
      this.routerOutlets.forEach((outlet: IonRouterOutlet) => {
        if (outlet && outlet.canGoBack()) {
            outlet.pop();
        } else if (this.router.url === '/tabs/tab1') {
          if (new Date().getTime() - this.lastTimeBackPress < this.timePeriodToExit) {
            navigator['app'].exitApp(); //Exit from app
            } else {
            this.presentAlertConfirm();
            this.lastTimeBackPress = new Date().getTime();
          }
          // navigator['app'].exitApp(); // work for ionic 4
        }
      });
    });
  }

  async presentAlertConfirm() {
    const alert = await this.alertController.create({
      // header: 'Confirm!',
      message: 'Are you sure you want to exit the app?',
      buttons: [
        {
          text: 'Cancel',
          role: 'cancel',
          cssClass: 'secondary',
          handler: (blah) => {
          }
        }, {
          text: 'Close App',
          handler: () => {
            navigator['app'].exitApp();
          }
        }
      ]
    });

    await alert.present();
  }

This is working when I am on front page(Tab1) and when I am on the other tabs it is not working and not going to the front page.

I think the problem is in my (outlet && outlet.canGoBack()) because this is not working. I am using the tab theme and Can I send the route to the main tab when the user is no other tabs and clicks the hardware back button.

I am using Ionic 4 tab theme.

Any help is much appreciated.

6
@JayOrdway.I have used that but It is not working. So can you please help me in this? - Raghav Kumar
@JayOrdway. Can you help me with the code for closing the app when the user double clicks on back button in Ionic 4? - Raghav Kumar
@JayOrdway. Can you help me with the solution? - Raghav Kumar
Magic77 seems to have the correct solution below - Jay Ordway

6 Answers

8
votes

Try This:

lastTimeBackPress = 0;
timePeriodToExit = 2000;
@ViewChildren(IonRouterOutlet) routerOutlets: QueryList < IonRouterOutlet > ;
backButtonEvent() {
  document.addEventListener("backbutton", async() => {
    try {
      const element = await this.modalCtrl.getTop();
      if (element) {
        element.dismiss();
        return;
      }
    } catch (error) {
      console.log(error);
    }
    this.routerOutlets.forEach(async(outlet: IonRouterOutlet) => {
      if (this.router.url != '/tabs/tab1') {
        await this.router.navigate(['/tabs/tab1']);
      } else if (this.router.url === '/tabs/tab1') {
        if (new Date().getTime() - this.lastTimeBackPress >= this.timePeriodToExit) {
          await this.presentAlertConfirm();
          this.lastTimeBackPress = new Date().getTime();
        }
        navigator['app'].exitApp(); // work for ionic 4
      }
    });
  });
}

And call this function in the constructor. This solved my problem because I am using the tabs theme and outlet.pop(); was not working. So I tried this method.

6
votes

Do it this Way.

constructor(private platform: Platform) {
  this.platform.backButton.subscribe(() => {

  });
}
6
votes

In response to @Raghav comment, I would try it like this:

lastTimeBackPress = 0;
timePeriodToExit = 2000;
@ViewChildren(IonRouterOutlet) routerOutlets: QueryList < IonRouterOutlet > ;

constructor(private platform: Platform) {
  this.backButtonEvent();
}

backButtonEvent() {
  this.platform.backButton.subscribeWithPriority(0, () => {
    this.routerOutlets.forEach(async(outlet: IonRouterOutlet) => {
      if (this.router.url != '/tabs/tab1') {
        await this.router.navigate(['/tabs/tab1']);
      } else if (this.router.url === '/tabs/tab1') {
        if (new Date().getTime() - this.lastTimeBackPress >= this.timePeriodToExit) {
          this.lastTimeBackPress = new Date().getTime();
          this.presentAlertConfirm();
        } else {
          navigator['app'].exitApp();
        }
      }
    });
  });
}

async presentAlertConfirm() {
  const alert = await this.alertController.create({
    // header: 'Confirm!',
    message: 'Are you sure you want to exit the app?',
    buttons: [{
      text: 'Cancel',
      role: 'cancel',
      cssClass: 'secondary',
      handler: (blah) => {}
    }, {
      text: 'Close App',
      handler: () => {
        navigator['app'].exitApp();
      }
    }]
  });

  await alert.present();
}
5
votes

That is because you are calling the registerBackButtonAction before platform is ready. You have to subscribe to the backbutton after the platform is ready. An approaching:

this.platform.ready().then(
  () => {
    this.platform.registerBackButtonAction(() => {
      this.platform.exitApp();
   });
  }
);
4
votes

try this in your app.component.ts

  lastTimeBackPress = 0;
  timePeriodToExit = 2000;
 @ViewChild(IonRouterOutlet, { static: false }) routerOutlets: IonRouterOutlet

constractor( private router: Router, private alertController: AlertController){this.backbutton()}


backbutton() {
console.log('backbutton')
document.addEventListener("backbutton", () => {
  console.log('backbutton1')
  if (this.routerOutlets && this.routerOutlets.canGoBack()) {
    this.routerOutlets.pop();
  }
  // else if (this.router.url != '/tabs/tabs/tab1') {
  //   this.router.navigate(['/tabs/tabs/tab1']);
  // } 
  else if (this.router.url === '/home') {
    if (new Date().getTime() - this.lastTimeBackPress >= this.timePeriodToExit) {
      this.lastTimeBackPress = new Date().getTime();
      this.presentAlertConfirm();
    } else {
      navigator['app'].exitApp();
    }
  }
});
  }



 async presentAlertConfirm() {
const alert = await this.alertController.create({
  // header: 'Confirm!',
  message: 'Are you sure you want to exit the app?',
  buttons: [{
    text: 'Cancel',
    role: 'cancel',
    cssClass: 'secondary',
    handler: (blah) => { }
  }, {
    text: 'Close App',
    handler: () => {
      navigator['app'].exitApp();
    }
  }]
});
await alert.present();
  }
1
votes

You can also try the following code snippets,

Make a change or add code like this in your app.component.ts file

import { Component, ViewChildren, QueryList } from '@angular/core';

import { Platform, IonRouterOutlet, ToastController } from '@ionic/angular';
import { SplashScreen } from '@ionic-native/splash-screen/ngx';
import { StatusBar } from '@ionic-native/status-bar/ngx';
import { Router } from '@angular/router';

@Component({
  selector: 'app-root',
  templateUrl: 'app.component.html',
  styleUrls: ['app.component.scss']
})
export class AppComponent {
  //code for exit app
  // set up hardware back button event.
  lastTimeBackPress = 0;
  timePeriodToExit = 2000;

  //code for exit app
  @ViewChildren(IonRouterOutlet) routerOutlets: QueryList<IonRouterOutlet>;
  constructor(
    private platform: Platform,
    private splashScreen: SplashScreen,
    private statusBar: StatusBar,
    private toastController: ToastController,
    private router: Router
  ) {
    this.initializeApp();
    // Initialize BackButton Eevent.
    this.backButtonEvent();
  }

  initializeApp() {
    this.platform.ready().then(() => {
      this.statusBar.styleLightContent();
      this.splashScreen.hide();
    });
  }
  
  // active hardware back button
  backButtonEvent() {
    this.platform.backButton.subscribe(async () => {

      this.routerOutlets.forEach(async (outlet: IonRouterOutlet) => {
        if (outlet && outlet.canGoBack()) {
          outlet.pop();

        } else if (this.router.url === '/home') {
          if (new Date().getTime() - this.lastTimeBackPress < this.timePeriodToExit) {
            // this.platform.exitApp(); // Exit from app
            navigator['app'].exitApp(); // work in ionic 4

          } else {
            const toast = await this.toastController.create({
              message: 'Press back again to exit App.',
              duration: 2000,
              position: 'middle'
            });
            toast.present();
            // console.log(JSON.stringify(toast));
            this.lastTimeBackPress = new Date().getTime();
          }
        }
      });
    });
  }
}

Make a change or add code like this in your home.ts file or where you want to user exit from your app page.

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

@Component({
  selector: 'app-home',
  templateUrl: 'home.page.html',
  styleUrls: ['home.page.scss'],
})
export class HomePage {
  public subscription: any;

  constructor(private platform: Platform) { }

  ionViewDidEnter() {
    this.subscription = this.platform.backButton.subscribe(() => {
      navigator['app'].exitApp();
    });
  }

  ionViewWillLeave() {
    this.subscription.unsubscribe();
  }
}