Customizing Android Back Button in Ionic 4

November 22nd 2019 Ionic 4 Android

Android hardware back button is something one can easily forget about but must in the end be properly supported in any mobile application. Unfortunately, built-in support in Ionic 4 is less than perfect. Many scenarios are still not properly supported as documented in a GitHub issue which hasn't been resolved for almost a year.

For example, when a side menu is opened, the back button doesn't close it as one would expect. Instead, it pops the top page from the navigation stack shown behind the side menu. To fix the behavior for a specific page, the following handler can be used:

private async onBack() {
  const openMenu = await this.menuCtrl.getOpen();
  if (openMenu) {
    await openMenu.close();
  } else {
    await this.navCtrl.pop();
  }
}

But how can such a handler be registered? In Ionic 3, the Platform service exposed the registerBackButtonAction function for this purpose. Ionic 4 doesn't have such a function in its Platform service anymore. Nor is there any other back button related functionality documented for this service.

There is however an undocumented backButton property in the service. It's an RxJS Subject you can subscribe to:

this.backButtonSub = this.platform.backButton.subscribe(() => this.onBack());

Unfortunately, if you do this, the default back button action will still execute along with the action in your handler. In the scenario described above, this means that the menu will close but the top page from the navigation stack will still pop as well.

To avoid this, the undocumented Ionic 4 specific subscribeWithPriority function can be used instead:

this.backButtonSub = this.platform.backButton.subscribeWithPriority(10000, () =>
  this.onBack()
);

Without documentation, one can only guess what value to use for the priority. A high enough value as in my example above does the trick, though. The default back button action is not executed anymore and the back button behaves as expected: if the side menu is open, it closes and the top page on the navigation stack remains intact.

To restrict this customized back button behavior to a single page, the handler should be registered in ionViewDidEnter and unregistered in ionViewWillLeave:

private backButtonSub: Subscription;

ionViewDidEnter() {
  this.backButtonSub = this.platform.backButton.subscribeWithPriority(
    10000,
    () => this.onBack()
  );
}

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

Since the approach is undocumented, I just hope that it won't stop working in a future update.

Copyright
Creative Commons License