Capacitor App Plugin addListener("backButton",...) doesn't work as Docs describe

I am creating an Android mobile app using Capacitor 6. My JavaScript app imports the Capacitor plugin “App” so that it can register an event listener for the hardware back button.

import { App } from "@capacitor/app"
App.addListener("backButton", this.onBackButton.bind(this))

The above code works, and my method “onBackButton” is called. The problem is that in addition to calling my callback method, it also navigates back to the previous page. This is contrary to the documentation here: App Capacitor Plugin API | Capacitor Documentation

The documentation at the above link states: " Listening for this event will disable the default back button behaviour, so you might want to call window.history.back() manually."

However this is not what actually happens. The default back button behavior is NOT disabled and still is executed, despite the fact that I am listening for this event.

How can I suppress the default back button behavior?

In your other post, you mentioned using Ionic with Vue. My guess is that Ionic is causing the “back” to continue.

Check out the Ionic back button docs - Hardware Back Button for Capacitor & Cordova on Android Devices. I use useBackButton to intercept the back button (back gesture on my Pixel 7) successfully.

2 Likes

I actually created my own composable around Ionic’s so I could override the behavior of IonBackButton. I wanted to warn the user if they had changes and hadn’t saved.

// back-navigation.ts

import { UseBackButtonResult, useBackButton, useIonRouter } from '@ionic/vue'

interface BackNavigationOptions {
    defaultUrl?: string
    onBack?: () => Promise<BackNavigationResult>
    setHardwareCallback: boolean
}

export interface BackNavigationResult {
    stopNavigation: boolean
}

export function useBackNavigation(options: BackNavigationOptions) {
    const ionicRouter = useIonRouter()
    let backButtonResult: UseBackButtonResult | undefined = undefined

    if (options.setHardwareCallback) {
        backButtonResult = useBackButton(50, handleBack)
    }

    async function handleBack(): Promise<void> {
        let result: BackNavigationResult = { stopNavigation: false }

        if (options.onBack != null) {
            result = await options.onBack()
        }

        if (result.stopNavigation) {
            return
        }

        // Follows similar logic to https://github.com/ionic-team/ionic-framework/blob/cdb4456be210b6d51beb8058b0feb21b283a8241/core/src/components/back-button/back-button.tsx#L115
        if (ionicRouter.canGoBack()) {
            ionicRouter.back()
        } else if (options.defaultUrl != null) {
            ionicRouter.replace(options.defaultUrl)
        }
    }

    function clearListeners(): void {
        backButtonResult?.unregister()
        backButtonResult = undefined
    }

    return {
        handleBack,
        clearListeners,
    }
}

This turned out to be the problem-- Ionic has it’s own “back-button” handling which was interfering with Capacitor’s. The solution was then simple-- I simply overrode Ionic’s back-button callback with a function that did nothing. And the problem went away.

1 Like