React-native-navigation: [V2][Android] Deficient documentation on activity re-creation

Created on 15 Mar 2019  路  8Comments  路  Source: wix/react-native-navigation

Issue Description

If your app sits in the background for a while, the Android system will sometimes kill the activity of your app to reclaim memory (this can be simulated by checking Do not keep activities in Settings -> Developer Options, and putting the app into the background, then bringing it back to the foreground).

In the case of RNN, when this activity "rebirth" occurs, the JavaScript context remains active (meaning the application state, eg components registered with RNN, are preserved), despite the view stack being destroyed.

This fact is not very intuitive, and is not noted anywhere in the RNN documentation; I think at a minimum, it would be useful to describe this case occurring, and noting that when this case is detected, you need to call setRoot, but most of the rest of RNN initialization you'd do on first boot is not relevant (eg registering components, starting some data layer aspect, etc). The way that we are presently handling this in our app is to set a boolean flag on the first call of our registerAppLaunchedListener callback (which, as JS state, is preserved between activity rebirth), and then on subsequent calls of that callback where the flag is true, we simply cycle our data layer and call setRoot, but skip the majority of the initialization.

I'm not sure how accurate this is, but I have suspicions that several Android related issues registered on this repo could be chalked up to this scenario, eg #4790, #4255, #4598, perhaps even #4675, etc.

Also worth noting (its not explicitly written in the docs, but can be gleamed from issues) is that the app launched event is not queued, so if you register a callback with registerAppLaunchedListener _after_ the event has been triggered by the native lib, you're just SOL -- given this, its absolutely crucial that as little as possible be done in your app before registering the launch listener, or else you might never get a callback of your listener.

I apologize for the length of this, and if anything is unclear please let me know and I will try to explicate further.

And if you'd like a PR for the documentation, I might be able to work something out for that; however I think getting an issue ticket linking to other issues that I believe could be symptomatic of the cause outlined here is at least a start, and should save other folks from going through the painful discovery of these facts that took me longer than I'd like to admit to figure out 馃榿

Edit: typos & grammar cleanup.

Steps to Reproduce / Code Snippets / Screenshots

Issue description gives an example of how to reproduce this (specifically paragraph 1 and 2).


Environment

  • React Native Navigation version: 2.0 (subsequent versions are also affected)
  • React Native version: 0.55.4 (likely more versions are affected)
  • Platform: Android
  • Device info: Samsung Galaxy S9 with Android 8.0.0 (can confirm that more Android devices and system software versions are affected)

Most helpful comment

hey guys, I've added another section to the docs about this - you're more than welcome to edit it and add more clarifications as needed 馃憤

All 8 comments

Totally agree with the issue - documentation is needed for this scenario which 100% going to occur. @ericketts congrats on taking the time / initiative to write it.

Also this is very important as well:
given this, its absolutely crucial that as little as possible be done in your app before registering the launch listener, or else you might never get a callback of your listener.

I spent half day or more to find why my listener was not working.

@ericketts regarding the work around you have done so that the JS part of your app does not load everything again when activity is re-initiated, in which version are you? I updated from 2.8.0 to 2.13.1 and the performance gain in activity re-initialization is big. Maybe you can try upgrade as well.

@marudy cheers thanks for the words of encouragement, I will certainly take a look at the new version -- I'm fairly sure that I tested this scenario on the latest release, despite us generally being on an older version of the lib.

Edit: to answer the question more directly, we're on a weird fork right now so we have v2.0.0 listed, but I believe its actually closer to v2.1.2 (shoutout to manhattan lol)

hey guys, I've added another section to the docs about this - you're more than welcome to edit it and add more clarifications as needed 馃憤

@guyca that is killer, thanks mate, I think this will really save people some hair pulling on an otherwise really fantastic library! cheers

Edit: I think the iOS bit is slightly confusing due to wording, I'll get in a PR for it tomorrow. thanks again Guy.

I'm still facing issues in Android during a cold start from a notification on the lock screen (cold start meaning the app has been killed from the Android multitasking view). Upon unlocking, the app is stuck on the splash screen. All code inside my index.js before and after Navigation.setRoot seem to work, and I'm able to see logs in my Chrome debugger as my app boots. But the logs related to RNN don't show up, such as Running application "ROOT" with appParams: ...

I moved Navigation.events().registerAppLaunchedListener(startApp); to be the first statement after my imports, as mentioned in the documentation linked by @guyca, but still no luck.

I don't face this issue if the app is not killed from the multitasking view.
I'm building a VoIP calling app where the app automatically wakes up on receiving a notification, and this is the only edge-case I'm not able to handle (ie., when the app is killed and device is locked).

Any help would be much appreciated!

@platonish remove all import statements and do only something like this:

// @flow
// top of file
const {Navigation} = require('react-native-navigation');
Navigation.events().registerAppLaunchedListener(async function appLaunched() {
  // do your 'import's as 'require's here
});
// bottom of file

Hi All,

I might be missing something but it appears that react-native-navigation does not handle when an Activity gets destroyed in the background by the Android OS. You can simulate this by setting "Don't keep activities" to true in the Developer Settings.

Here is a little GIF of what happens when you background the sample playground app with "Don't keep activities" set to false and then to true:

May-05-2019 09-44-43

I'm hoping I'm missing something and this has been solved already. If it has, let me know and I'll update the playground app to exhibit the desired result of not restarting the entire stack when the Activity has been destroyed by the Android OS.

Thanks!

(Separate issue created here: https://github.com/wix/react-native-navigation/issues/5071)

Was this page helpful?
0 / 5 - 0 ratings