Testing app lifecycle


#1

I have a really annoying crash in my app.

Sometimes after it’s been inactive for a long time and I launch it again it seems to resume to it’s prior state but then just exits.

To debug this, I need to simulate the various stages of the app life cycle, how do I do this?
Preferably on the Android emulator.


#2

Have you tried toying around with settings in the Developer Options section of the device? A user on SO suggests turning on one in particular, might be worth giving it a try - https://stackoverflow.com/a/19622671/6408287, at least so long as activity going in background and back in foreground is concerned.


#3

Thank you for the suggestion.

Unfortunately it’s not exactly what I need.

I’m pretty sure the activity haven’t been destroyed when this happens.
Just for a moment I see the last view before the app exists again, with that option enabled the app launches again from the launch screen.


#4

There could be a lot of different things causing your crash. Mostly likely dependent on your particular app. That is why you are asking to see exactly what state your app is in. I also just had to debug a feature because it turns out my app is still tracking orientation changes even when it’s paused and in the background.

So what I did was 2 things.

In my app.js, I put in logs for all the state changes, so I know for sure what is going on.

Then in each page that I also need to track, I add them again as needed. Because you might want to know if your page or app is getting the state change first. In my case it was my main-page.js where the error was triggered.

Also there is more info at https://docs.nativescript.org/core-concepts/application-lifecycle

I have some extra things here. You want the suspend and resume events.



var application = require("application");

application.on(application.launchEvent, function(args) {
    if (args.android) {
        // For Android applications, args.android is an android.content.Intent class.
        console.log("Launched Android application with the following intent: " + args.android + ".");
    } else if (args.ios !== undefined) {
        // For iOS applications, args.ios is NSDictionary (launchOptions).
        console.log("Launched iOS application with options: " + args.ios);
    }
});

application.on(application.suspendEvent, function(args) {
    if (args.android) {
        // For Android applications, args.android is an android activity class.
        console.log("app Activity suspendEvent: " + args.android);
    } else if (args.ios) {
        // For iOS applications, args.ios is UIApplication.
        console.log("app UIApplication suspendEvent: " + args.ios);
    }
});

application.on(application.resumeEvent, function(args) {
    if (args.android) {
        // For Android applications, args.android is an android activity class.
        console.log("app Activity resumeEvent: " + args.android);
    } else if (args.ios) {
        // For iOS applications, args.ios is UIApplication.
        console.log("app UIApplication resumeEvent: " + args.ios);
    }
});

application.on(application.exitEvent, function(args) {
    if (args.android) {
        // For Android applications, args.android is an android activity class.
        console.log("Activity: " + args.android);
    } else if (args.ios) {
        // For iOS applications, args.ios is UIApplication.
        console.log("UIApplication: " + args.ios);
    }
});

application.on(application.lowMemoryEvent, function(args) {
    if (args.android) {
        // For Android applications, args.android is an android activity class.
        console.log("Activity: " + args.android);
    } else if (args.ios) {
        // For iOS applications, args.ios is UIApplication.
        console.log("UIApplication: " + args.ios);
    }
});

application.on(application.uncaughtErrorEvent, function(args) {
    if (args.android) {
        // For Android applications, args.android is an NativeScriptError.
        console.log("NativeScriptError: " + args.android);
    } else if (args.ios) {
        // For iOS applications, args.ios is NativeScriptError.
        console.log("NativeScriptError: " + args.ios);
    }
});

application.on(application.orientationChangedEvent, function(args) {
    // args.android exists if on Android
    if (args.android) {
        console.log("app Android orientationChangedEvent: " + args.newValue);
        // args.ios exists if on iOS
    } else if (args.ios) {
        console.log("app iOS orientationChangedEvent: " + args.newValue);
    }
});

#5

Thanks, but I know about those events :slight_smile:

I was looking for a way to intentionally trigger the various life cycle states, in the hope I could reproduce the crash consistently.

You mentioned something about the orientation changes event. We use the nativescript-orientation plugin, did you use this too or did you have your own event?


#6

You could try toying with the android tooling then. Namely, adb AM (Activity Manager) and adb monkey.

https://developer.android.com/studio/command-line/adb.html#am

https://developer.android.com/studio/test/monkey.html


#7

Thank you.

I’ll look into those :slight_smile:


#8

I’m tracking orientation changes on my own. On the page where I am showing Admob smart banners, I need to know when the orientation changes to force the banners to re-size to the new screen width. I am tracking iOS separately from Android for testing (Android sends orientation changes while in the background while iOS does not.)


exports.pageLoaded = function(args) {
    console.log("pageLoaded");
   
    ....

    // http://docs.nativescript.org/api-reference/interfaces/_application_.orientationchangedeventdata.html
    application.on(application.orientationChangedEvent, orientationChanged);
};

exports.pageUnloaded = function() {
    console.log("pageUnloaded");
    // https://stackoverflow.com/questions/35908494/does-anybody-know-how-to-detect-orientation-change-for-nativescript
    // We don't want events while page is in the background
    application.off(application.orientationChangedEvent, orientationChanged);
};

function orientationChanged(args) {

    // FYI, smart banners won't resize on an orientation change, so we need to re-create them

    // args.android exists if on Android
    if (args.android) {
        console.log("main Android orientationChangedEvent: " + args.newValue);
        createAdmobBanner();

    } else if (args.ios) { // args.ios exists if on iOS
        console.log("main iOS orientationChangedEvent: " + args.newValue);
        createAdmobBanner();
    }
}