NativeScript - Capturing the Back Button on Android

Quite frequently you want to control what happens when your user hits the back button, well this is actually pretty simple to do on Android.  I've seen this question pop up several times; so it makes good blog post fodder.

You can either do this totally globally; or on a per page basis.   Globally, you just need to add the following code to your app.js file:

Global Event Handler:

// application variable should already be included in the app.js file
// Only do this on android
if (application.android) {
  application.android.on(application.AndroidApplication.activityBackPressedEvent, backEvent);
}

// This does the work on deciding if you want to go back
// arg.cancel = true will cancel navigating back
function backEvent(args) {
   if (dontGoBack) { args.cancel = true; }
}

You just need to figure out what your criteria is to handle canceling going back.

 

Individual Page Handler:

Now I personally prefer to put the handler on each page I need it on; so it is a little bit different.

You need to have a pageLoaded and a pageUnloaded event.

// Somewhere at the top
var application = require('application');

// Somewhere in your page you need to register your handler
exports.pageLoaded = function() {
    // We only want to register the event in Android
    if (application.android) {
        application.android.on(application.AndroidApplication.activityBackPressedEvent, backEvent);
    }
};

// When we navigate away from this page, we need to de-register the handler.
exports.pageUnloaded = function() {
    // We only want to un-register the event on Android
    if (application.android) {
        application.android.off(application.AndroidApplication.activityBackPressedEvent, backEvent);
    }
};

// This does your checks to see if you want to go back
// setting cancel=true will cancel the back 
function backEvent(args) {
  if (iRefuseToGoBack) { args.cancel = true; }
}

In your page.xml your "Page" declaration should look like:
<Page xmlns="http://schemas.nativescript.org/tns.xsd"
      loaded="pageLoaded" unloaded="pageUnloaded">

You might notice in the individual page view version I register and de-register the event.  Each time the page is loaded it will register the event, if you don't de-register the event then that event handler will STILL run each time you hit the back button.  So it is very important if you are not using a global handler, to register on load, and de-register on unload.

 

Advanced Global Technique:

There is one other way to do this; I created this technique in my nativescript-orientation plugin and as I was finishing up this post I realized it could apply here and eliminates all the busy work of registering and de-registering handlers on each page but allows you per-page handlers.  I'm actually going to switch my apps to this way; because now that I wrote it -- it is my favorite way.  🙂

In your app.js file:

var frame = require('ui/frame');
if (application.android) {
    application.android.on(application.AndroidApplication.activityBackPressedEvent, backEvent);
}

function backEvent(args) {
    var currentPage = frame.topmost().currentPage;
    if (currentPage &amp;&amp; currentPage.exports &amp;&amp; typeof currentPage.exports.backEvent === "function") {
         currentPage.exports.backEvent(args);
   }   
}

Then in any page you want to control the back Event you do:
exports.backEvent = function(args) {
  if (iDontReallyWantToGoBack) { args.cancel = true; }
}

Pretty simple you only need to have a single global register; and it checks to see if the current page has a back handler which it will call if it exists.

Have fun, and now we can all stop going back.  😀

13 thoughts on “NativeScript - Capturing the Back Button on Android

      1. Srinivasa Rao S

        Hi Anderson,
        Angular way requires minimal changes. As module import and binding events are little different.

        Here is the angular way,
        import * as application from "application";

        ngAfterViewInit() {
        if (application.android) {
        application.android.on(application.AndroidApplication.activityBackPressedEvent, this.backEvent);
        }
        }

        ngOnDestroy() {
        // cleaning up references/listeners.
        if (application.android) {
        application.android.off(application.AndroidApplication.activityBackPressedEvent, this.backEvent);
        }
        }

        backEvent(args){
        if(this.isRefuseToGoBack){
        args.cancel = true;
        return;
        }
        }

        However i'm facing problem with the isRefuseToGoBack variable, it is always undefined in backEvent. Except this issue its working as expected.

        Reply
        1. Nathanael Anderson Post author

          Awesome thanks for the code update of Angular Native. On your this.isRefuseToGoBack issue, did you create a isRefuseToGoBack variable inside your class?

          Reply
        2. Claudio Wettstein

          to bind the correct "this" use:

          backEvent = (args) => {
          if(this.isRefuseToGoBack){
          args.cancel = true;
          return;
          }
          }

          Reply
    1. Nathanael Anderson Post author

      Sorry, I have no idea. I haven't had a chance to investigate Angular2 in context with this design.

      Reply
    1. Nathanael Anderson Post author

      If you can duplicate this issue; I would recommend you put a new issue up on the NativeScript Github Issues so that it can be fixed in a future version...

      Reply

Leave a Reply

Your email address will not be published. Required fields are marked *