Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v4: Android hardware back button doesn't work #14803

Closed
artemtool opened this issue Jul 19, 2018 · 19 comments
Closed

v4: Android hardware back button doesn't work #14803

artemtool opened this issue Jul 19, 2018 · 19 comments
Assignees

Comments

@artemtool
Copy link

Bug Report

Ionic Info
Run ionic info from a terminal/cmd prompt and paste the output below.

Ionic:

   ionic (Ionic CLI)          : 4.0.0-rc.9 (C:\Users\ape\AppData\Roaming\npm\node_modules\ionic)
   Ionic Framework            : @ionic/angular 4.0.0-alpha.7
   @angular-devkit/core       : 0.6.8
   @angular-devkit/schematics : 0.6.8
   @angular/cli               : 6.0.8
   @ionic/ng-toolkit          : not installed
   @ionic/schematics-angular  : 1.0.0-rc.9

Cordova:

   cordova (Cordova CLI) : 8.0.0
   Cordova Platforms     : android 6.3.0 ios 4.5.4

System:

   Android SDK Tools : 25.2.5
   NodeJS            : v10.5.0 (C:\Program Files\nodejs\node.exe)
   npm               : 6.1.0
   OS                : Windows 10

Describe the Bug
Android hardware button doesn't work as intended. It seems to be because of back button behavior overriding in generated cordova.js:

var backButtonChannel = cordova.addDocumentEventHandler('backbutton');
        backButtonChannel.onHasSubscribersChange = function() {
            // If we just attached the first handler or detached the last handler,
            // let native know we need to override the back button.
            exec(null, null, APP_PLUGIN_NAME, "overrideBackbutton", [this.numHandlers == 1]);
        };

which is caused by:

https://github.com/ionic-team/ionic/blob/181cd559cc68542d48a33e6ff58408e2ffc2077c/angular/src/providers/platform.ts#L42

Steps to Reproduce
Steps to reproduce the behavior:

  1. Clone repo https://github.com/ionictheme/ionic4-start-theme
  2. Install deps and run on device
  3. Click on android hardware back button
  4. Nothing happens

Expected Behavior
Android hardware back button should return the previous page or exit app.

@pvskasyrskiy
Copy link

Are there any updates about this bug?

@naveedahmed1
Copy link

Will it be supported by default in Ionic 4 or are the developers supposed to use approach like this https://stackoverflow.com/a/51729093/2755616

@Farbdose
Copy link

@pvskasyrskiy @artemtool the workaround mentioned by @naveedahmed1

Will it be supported by default in Ionic 4 or are the developers supposed to use approach like this https://stackoverflow.com/a/51729093/2755616

Was just confirmed working

@crebuh
Copy link

crebuh commented Aug 30, 2018

Works for me but just for pages outside of the tabs page? Inside tabs page I have 4 additional router-outlets how to handle this navigation stack?

@naveedahmed1
Copy link

There are other cases as well, such as Back button for modal does't work either.

Just keep this in mind that the solution on stackoverflow is a temporary fix. we should wait for permanent fix from ionic team, which I believe should cover all cases and should be available in next updates.

@naveedahmed1
Copy link

Just to bring it into notice, the fix should work for the nested router outlets as well. For example for the cases where app component has:

<ion-router-outlet main></ion-router-outlet>

and a component A is rendered in this outlet which also has a router outlet for child components

<ion-router-outlet main></ion-router-outlet>

@crebuh
Copy link

crebuh commented Aug 31, 2018

@naveedahmed1

for pages inside the TabsPage it is not working for me. I added this workaround in the TabsPage instead:

export class TabsPage {

    @ViewChildren(IonRouterOutlet) routerOutlets: QueryList<IonRouterOutlet>;

    constructor(
        private platform: Platform,
        private router: Router
    ) {
        // subscription to native back button
        this.platform.backButton.subscribe(() => {
            this.routerOutlets.forEach((outlet: IonRouterOutlet) => {
                if (outlet && outlet.canGoBack()) {
                    outlet.pop();
                }
            });
        });
    }
}

@manucorporat manucorporat self-assigned this Sep 4, 2018
@redhaanggara
Copy link

also ionic 4 cant close app, how to solved it?

@borgogelli
Copy link

Back button should be the priority of the Ionic's dev team

@crebuh
Copy link

crebuh commented Sep 7, 2018

I guess it has been fixed recently? dfac9dc

@peterpeterparker
Copy link
Contributor

@borgogelli see how many commits they did about that subject recently, it definitely looks like it's one of their priorities

@crebuh for me it worked with modals but not yet with navigation #15492

@Riyaz0001
Copy link

Riyaz0001 commented Sep 15, 2018

Try This:


export class AppComponent {

    // set up hardware back button event.
    lastTimeBackPress = 0;
    timePeriodToExit = 2000;

    @ViewChildren(IonRouterOutlet) routerOutlets: QueryList<IonRouterOutlet>;

    constructor(
        private platform: Platform,
        private splashScreen: SplashScreen,
        private statusBar: StatusBar,
        public modalCtrl: ModalController,
        private menu: MenuController,
        private actionSheetCtrl: ActionSheetController,
        private popoverCtrl: PopoverController,
        private router: Router,
        private toast: Toast) {
        this.initializeApp();
        // Initialize BackButton Eevent.
        this.backButtonEvent();
    }


// active hardware back button
    backButtonEvent() {
        this.platform.backButton.subscribe(async () => {
            // close action sheet
            try {
                const element = await this.actionSheetCtrl.getTop();
                if (element) {
                    element.dismiss();
                    return;
                }
            } catch (error) {
            }

            // close popover
            try {
                const element = await this.popoverCtrl.getTop();
                if (element) {
                    element.dismiss();
                    return;
                }
            } catch (error) {
            }

            // close modal
            try {
                const element = await this.modalCtrl.getTop();
                if (element) {
                    element.dismiss();
                    return;
                }
            } catch (error) {
                console.log(error);

            }

            // close side menua
            try {
                const element = await this.menu.getOpen();
                if (element !== null) {
                    this.menu.close();
                    return;

                }

            } catch (error) {

            }

            this.routerOutlets.forEach((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 {
                        this.toast.show(
                            `Press back again to exit App.`,
                            '2000',
                            'center')
                            .subscribe(toast => {
                                // console.log(JSON.stringify(toast));
                            });
                        this.lastTimeBackPress = new Date().getTime();
                    }
                }
            });
        });
    }

Update: it's work for me.

@Riyaz0001
Copy link

Riyaz0001 commented Sep 15, 2018

this.platform.exitApp(); doesn't work for ionic v4.1.2

@redhaanggara
Copy link

this.platform.exitApp(); doesn't work for ionic v4.1.2

@Riyaz0001
Copy link

Riyaz0001 commented Sep 16, 2018

this.platform.exitApp(); doesn't work for ionic v4.1.2

replace this.platform.exitApp() and use navigator['app'].exitApp(); // work for ionic 4

@redhaanggara
Copy link

navigator['app'].exitApp(); how yo setup it?

@ptitjes
Copy link
Contributor

ptitjes commented Sep 21, 2018

@manucorporat PR #15615 fixes the remaining problem with the handler registered by overlays.tsx.

@nharrer
Copy link

nharrer commented Oct 8, 2018

The temporary fix from @Riyaz0001 worked for me. However when there are controls on the page I go back to via the physical back button, the first tap on a control does not work. For example a plain ion-button:

<ion-button (click)="doit()">Test</ion-button>

I have to tap it twice in order for doit() to be called. It does not happen, when I got back with the <ion-back-button>. Only with the physical back button and the backButtonEvent().

@ionitron-bot
Copy link

ionitron-bot bot commented Nov 7, 2018

Thanks for the issue! This issue is being locked to prevent comments that are not relevant to the original issue. If this is still an issue with the latest version of Ionic, please create a new issue and ensure the template is fully filled out.

@ionitron-bot ionitron-bot bot locked and limited conversation to collaborators Nov 7, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests