Hardware back button destroys the app

I’m an Ionic 5.6 application with Angular 12, the problem is when I press the hardware back button anywhere in the app, my app gets closed.
I’ve subscribed the backButton in my home page component like this

 platform.backButton.subscribeWithPriority(1, () => {
      if (this.router.url === '/home')
      {
        this.router.navigate(['/home']);

        return;
      }
      else
      {
        this.location.back();
      }

    });

But even if I completely remove this code, I still have the same behavior.
What could possibly be the problem.

This is the logcat logs when I press the hardware back button

2021-07-04 13:31:30.348 8980-8980/com.garageapp.user D/Capacitor: App paused
2021-07-04 13:31:30.966 8980-8980/com.garageapp.user D/Capacitor: App stopped
2021-07-04 13:31:30.973 8980-8980/com.garageapp.user D/Capacitor: App destroyed

1 Like

yes , i have the same problem , :grimacing: :upside_down_face:

I solved the problem by creating the new project and copying all the content from the buggy project, new project is now working perfectly Alhamdulillah

1 Like

Please try this (tested on Ionic 5.3):

//ON BACKBUTTON
this.platform.backButton.subscribeWithPriority(9999, () => {

	//Disable default backbutton behavior
	document.addEventListener("backbutton", function(event) {
	  event.preventDefault(); event.stopPropagation();
	}, false);

	//Custom backbutton behavior
	// YOUR CODE HERE
});

You need to disable the default behavior before execute your code. Adding custom event listener to “backbutton” should help.

2 Likes

First of all you need to learn more about how to handle back button behaviour.

  1. You need to verify in which page your current navigation occurs by using
if(this.router.url == '/home' && this.router.isActive('/home', true)){
}

platform.backbutton.subscribeWithPriority, platform.backbutton.subscribe or whatever the backbutton subscription method is, the function once executed entirely watch for backbutton activity in all your pages. You can check this behaviour by adding a dummy console to print in your devTools console. It will print the console you added, in every page you try to exit for your current code. Just use the above condition and you problem will be solved.

1 Like

this is not about the router, no matter on which page or component i press, it instantly crash the app, and the execution doesn’t even reach this router code

Can you reproduce this issue in an Ionic starter app and provide a link to the repo?

No, new app won’t have this error, this is in my app, but I can’t find the reason which is causing this error to trigger

Do you have the @capacitor/app plugin installed?

I disagree strongly with this suggestion, because it introduces needless and hard-to-see dependencies between different bits of code.

If the back button is supposed to behave in a special way when a particular page is active, that is (IMHO) a perfect case for lifecycle events: set up the way the back button is supposed to behave when the user is interacting with a FooPage in FooPage’s ionViewWillEnter and tear it down in ionViewDidLeave. That way all the relevant code is in foo.page.ts: the handler itself, along with the code that registers and deregisters it.

1 Like

Please provide the code of the page in which the error occurs. Because you said the problem is not about router. But your code says it depends on router and platform backbutton. So I can help you

Your issue can be solved by including my code block inside a backbutton subscription

ionViewDidEnter(){
this.platform.backButton.subscribe(()=>{ 
if(this.router.url == '/home' && this.router.isActive('/home', true)){
}});
}
somefunction(){
if(some condition){
console.log(this.platform.backButton.observers);
var observers=this.platform.backButton.observers;
this.platform.backButton.observers=[];
console.log(this.platform.backButton.observers);
this.platform.backButton.subscribe(()=>{
console.log(this.platform.backButton.observers);
//other activity
setTimeout(()=>{
this.platform.backButton.observers=observers;
},50);
});
}
}

Here backbutton behaviour is set to listen to only the specified one. Read more about backbutton observers. You cannot control your backbutton by subscription with priority or normal subscription alone. But you can control it additionally with backbutton observers. After running the above code check your console. You will find three observers array in console. 1st one is the updated observer in your current page. 2nd one is emptied observers. 3rd one is updated observer from subscription we added in our somefunction(). Try it. It will work

Sorry, but I’m having a hard time making any sense out of this post, so I’ll try just rephrasing my concern.

Any code - including a backbutton handler - that needs to behave differently depending on what page is currently being interacted with, can be implemented in two ways.

Option A: have one single handler function with a big if/else switch cascade. If we’re on page A, do A. If we’re on page B, do B. If we’re on page C, do C. This is what I understand you’re advocating.

Option B: have one handler function per page. Register the page A handler (that does A) when page A becomes current, using lifecycle events to know when that happens. Deregister the page A handler when that page leaves. Register the page B handler (that does B) when page B becomes current, and so on.

I prefer option B for three reasons:

  1. It makes for smaller functions. Smaller functions are easier to read and understand.
  2. If/else and switch/case are notorious sources of bugs, because things fall through the cracks in ways that aren’t easily visible. I call this “negative space code”, where you have to understand both what is happening and what isn’t happening.
  3. All code specific to page X should be in x.page.ts, to the extent humanly possible. That way, when we get a bug report about page X, we know exactly where to start looking. Also, when somebody looking to change how page X works, they know everywhere they have to pay attention to. If the back button handler is in app.component.ts, that’s not obvious to me when I rearchitect the router URLs because somebody in marketing wants “prettier” URLs or now the back button should do C when the user’s on page A, instead of A like it used to.

So, in conclusion, I don’t like the smell of back button handlers that query the router for state, because it means that they’re monolithic functions trying to affect the behavior of distant parts of the app, and that smells like spaghetti to me.

No, I don’t have this installed

On any page, if I press the hardware button the app crashes

If you wish, please share your project repo… I will find the bug

The @capacitor/app plugin is required for hardware back button functionality to work: Capacitor - build cross platform apps with the web

3 Likes

Thank you so much @ldebeasi I was scratching my head around this problem for more than 5 days, I don’t know how accidentally I removed this from package.json
I made a complete new ionic project and copied all the code from previous manually (where it was causing this bug) just to solve this, but your solution worked like a charm.
Thanks again

1 Like

@idebeasi thanks man this is work for me

from last 2 or 3 days when i migrate my Ionic app into capacitor 3 i am facing problem with hardware back button, whenever i pressed back button withing my app on any page it exit my app

Because platform.backButton.subscribeWithPriority function is not work after migration into capacitor 3

Quick update: We updated the Capacitor v3 docs to explain the plugin requirement a bit better: Capacitor - build cross platform apps with the web

2 Likes