我的硬件 'Back Button Action' 在 Ionic 4 中不工作

My Hardware 'Back Button Action' is not working in Ionic 4

我正在使用我的 Ionic 4 应用程序,当用户在移动设备后退按钮上单击 2 次时,它应该会关闭该应用程序,但这并没有发生。

这是我的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();
  }

当我在首页 (Tab1) 时,它可以工作,而当我在其他选项卡时,它不工作,也不会转到首页。

我认为问题出在我的 (outlet && outlet.canGoBack()) 因为这不起作用。我正在使用选项卡主题,当用户没有其他选项卡并单击硬件后退按钮。

I am using Ionic 4 tab theme.

非常感谢任何帮助。

那是因为您在平台准备就绪之前调用了 registerBackButtonAction。平台准备就绪后,您必须订阅后退按钮。一个接近:

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

这样做。

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

  });
}

试试这个:

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
      }
    });
  });
}

并在构造函数中调用这个函数。这解决了我的问题,因为我正在使用选项卡主题并且 outlet.pop(); 不工作。所以我尝试了这个方法。

为了回应@Raghav 的评论,我会这样尝试:

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();
}

在您的 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();
  }

您也可以尝试以下代码片段,

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();
  }
}

试试这个

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

import {IonRouterOutlet, Platform, 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';
import {Location} from '@angular/common';

@Component({
    selector: 'app-root',
    templateUrl: 'app.component.html',
    styleUrls: ['app.component.scss']
})
export class AppComponent {

    lastTimeBackPress = 0;
    timePeriodToExit = 2000;

    // @ts-ignore
    @ViewChildren(IonRouterOutlet) routerOutlets: QueryList<IonRouterOutlet>;

    constructor(
        private platform: Platform,
        private splashScreen: SplashScreen,
        private statusBar: StatusBar,
        private toastController: ToastController,
        private router: Router,
        private location: Location
    ) {
        this.initializeApp();
    }

    initializeApp() {
        this.platform.ready().then(() => {
           
            this.backButtonEvent();
        });
    }

    // active hardware back button
    backButtonEvent() {
        this.platform.backButton.subscribeWithPriority(0, () => {
            this.routerOutlets.forEach(async () => {
                if (this.router.url !== '/tabs/home') {
                    await this.location.back();
                } else {
                    if (new Date().getTime() - this.lastTimeBackPress < this.timePeriodToExit) {
                        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();
                    }
                }
            });
        });
    }
}