Hardware Back button handler does not work for the first page of the app

I’m trying to prevent the back/exit function triggered by the default Android back button. For that I’m using Hardware Back Button, but it doesn’t work on Android 11 devices (SDK 30). When testing on other versions the override works as expected.

Function currently used:

constructor(private platform: Platform) {
	this.platform.backButton.subscribeWithPriority(9999, () => { // Tried to put absurd number for test
		console.log('Handler was called!');
	});
}

Other Failed Attempts:

1

@HostListener('document:ionBackButton', ['$event'])
private overrideHardwareBackAction($event: any) {
	$event.detail.register(100, () => {
		return;
	});				
}

2

this.platform.ready().then(() => {
	document.addEventListener('backbutton', () => {
		console.log('backButton handler was called!');
	}, false);

	document.addEventListener('backbutton', () => {
		console.log('backButton handler was called!');
	}, true);
});

3

ionViewDidEnter() {
	document.addEventListener("backbutton",function(e) {
	  // Do nothing
	}, false);
}

4 (Don’t make much sense here because uses ion-back-button)

import { IonBackButtonDelegate } from '@ionic/angular';

...

export class TestPage {

  @ViewChild(IonBackButtonDelegate, { static: false }) backButton: IonBackButtonDelegate;

  ...
  // Registering
  ionViewDidEnter() {
    console.log('ionViewDidEnter');
    this.setUIBackButtonAction();
  }

  setUIBackButtonAction() {
    this.backButton.onClick = () => {
      // handle custom action here
    };
  }
}
2 Likes

Fixed by putting the method in ngOnInit() and not in the constructor as show in documentation. Possibly I got this error because I wanted to handle the error in the first page of the app.

ngOnInit() {
    this.platform.backButton.subscribeWithPriority(9999, () => {
        console.log('backButton handler was called!');
    });
}

ionViewDidLeave() {
    this.platform.backButton.unsubscribe();
}

Not really a solution because don’t work 100%, just some times

I think the actual problem here is that you’re trying to interact with the platform before it’s ready, and shifting the call to ngOnInit simply kicks the can and makes the race condition less likely to bite you.

I would instead suggest that whereever you try to register the back button handler, you do it in a then clause after Platform.ready has resolved.

Thank you for the reply. This was actually the first thing I tried, it was my mistake in not adding it to the main post. But I was doing this directly inside the constructor(), even so the function didn’t work, only after moving to ngOnInit().

Still, this is kind of counter-intuitive, but add:

this.platform.ready().then(() => {
    console.log('platform ready') // Can see the log
    this.platform.backButton.subscribeWithPriority(9999, () => {
        console.log('backbutton handler activated') // Is never fired
    });
});

even on ngOnInit has a worse effect than without. Whenever the app starts and I try to hit the Android back button the app just closes, the function doesn’t fall into the handler. This happens more rarely without platform.ready(). If you have any suggestions on how I can make this work 100% of the time I would be happy to give it a try.

Remembering that I just want to make this handler for the first page that the app opens.

Some tests:
Android 5: Working 100%
Android 9, 10 & 11: Work just some times, 100% if I go to another page and then come back to the first one.

Just out of curiosity, is there a reason why you don’t want to close the app when the back button is pressed on the first page/screen when the app opens? I ask because it is the standard Android experience that upon pressing the back button or using the back gesture for the current app to close if it was just opened and is on its first screen.

It was a demand from my users.

1 Like