Hello!
MainActivity.onCreate() always seems to get null for its savedInstanceState parameter: firstly when the app starts, as expected, but then each time the app wakes after being backgrounded, every time the savedInstanceState parameter is null.null for savedInstanceState, again, and subsequent calls are either passed a proper Bundle of parcelled data, or aren't made at all.The post-launch null Bundles are problematic for us as we expect to be able to do initialisation work in onCreate() - or at least to be able to use state data (saved in onSaveInstanceState() and passed in via onCreate's savedInstanceState parameter) to reconstruct our state in a new Activity if the OS kills the previous one. However what's actually happening is that on the first run of an app, when it's backgrounded and then foregrounded again, the Activity receives onCreate(null) a second time, so we have no chance to reconstruct any state as the passed-in Bundle is null, meaning the initialisation code overwrites any state, and our app-startup code gets properly tangled.
I looked at ReactActivity but all I can see is that its onCreate() method just calls super.onCreate() in android.app.Activity and then mDelegate.onCreate(), and I haven't been able to track this much further into RN so I don't know why this is happening, or the answer to any of these questions:
savedInstanceState's Bundle null in release mode? Any help or input would be very much appreciated, thanks!
package com.yourapp;
import android.os.Bundle;
import android.util.Log;
import com.facebook.react.ReactActivity;
public class MainActivity extends ReactActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d( "ReactNativeDebugOutput", "MainActivity::onCreate() " + savedInstanceState );
}
@Override
protected void onStart() {
super.onStart();
Log.d( "ReactNativeDebugOutput", "MainActivity::onStart()" );
}
@Override
protected void onRestart() {
super.onRestart();
Log.d( "ReactNativeDebugOutput", "MainActivity::onRestart()" );
}
@Override
protected void onResume() {
super.onResume();
Log.d( "ReactNativeDebugOutput", "MainActivity::onResume()" );
}
@Override
protected void onPause() {
super.onPause();
Log.d( "ReactNativeDebugOutput", "MainActivity::onPause()" );
}
@Override
protected void onStop() {
super.onStop();
Log.d( "ReactNativeDebugOutput", "MainActivity::onStop()" );
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.d( "ReactNativeDebugOutput", "MainActivity::onDestroy()" );
}
@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
Log.d( "ReactNativeDebugOutput", "MainActivity::onSaveInstanceState() " + savedInstanceState );
}
@Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
Log.d( "ReactNativeDebugOutput", "MainActivity::onRestoreInstanceState() " + savedInstanceState );
}
/**
* Returns the name of the main component registered from JavaScript.
* This is used to schedule rendering of the component.
*/
@Override
protected String getMainComponentName() {
return "YourAppName";
}
}
2a. Run app in debug mode via Android Studio.
2b. Hit the home button to background the app
2c. Restart the app by tapping its icon
2d. Check the logs
2e. Kill the app using the process manager
2f. Start the app by tapping its icon
2g. Repeat steps 2b-2d
3a. Run app in release mode via react-native run-android --variant=release.
3b. Hit the home button to background the app
3c. Restart the app by tapping its icon
3d. Check the logs
3e. Kill the app using the process manager
3f. Start the app by tapping its icon
3g. Repeat steps 3b-3d
For each run, in debug and release mode respectively, I expect to see MainActivity::onCreate() null printed only once to the log, when the app is started and the activity in created, with any subsequent calls printing out a proper serialized Bundle value, passed in as savedInstanceState.
In debug mode, the results are as expected:
First run, immediately on being built & installed by Android Studio:
$ adb logcat | grep ReactNativeDebugOutput
D/ReactNativeDebugOutput(22588): MainActivity::onCreate() null
D/ReactNativeDebugOutput(22588): MainActivity::onStart()
D/ReactNativeDebugOutput(22588): MainActivity::onResume()
D/ReactNativeDebugOutput(22588): MainActivity::onPause()
D/ReactNativeDebugOutput(22588): MainActivity::onSaveInstanceState() Bundle[{android:viewHierarchyState=Bundle[{android:views={1=android.view.AbsSavedState$1@1244c50f, 4=android.view.AbsSavedState$1@1244c50f, 8=android.view.AbsSavedState$1@1244c50f, 9=android.view.AbsSavedState$1@1244c50f, 13=android.view.AbsSavedState$1@1244c50f, 14=android.view.AbsSavedState$1@1244c50f, 15=android.view.AbsSavedState$1@1244c50f, 16=android.view.AbsSavedState$1@1244c50f, 18=android.view.AbsSavedState$1@1244c50f, 22=android.view.AbsSavedState$1@1244c50f, 25=android.view.AbsSavedState$1@1244c50f, 29=HorizontalScrollView.SavedState{33eca99c scrollPosition=0 isLayoutRtl=false}, 30=android.view.AbsSavedState$1@1244c50f, 32=android.view.AbsSavedState$1@1244c50f, 33=android.view.AbsSavedState$1@1244c50f, 36=android.view.AbsSavedState$1@1244c50f, 38=android.view.AbsSavedState$1@1244c50f, 39=android.view.AbsSavedState$1@1244c50f, 43=android.view.AbsSavedState$1@1244c50f, 45=android.view.AbsSavedState$1@1244c50f, 47=android.view.AbsSavedState$1@1244c50f, 49=android.view.AbsSavedState$1@1244c50f, 50=android.view.AbsSavedState$1@1244c50f, 54=android.view.AbsSavedState$1@1244c50f, 57=android.view.AbsSavedState$1@1244c50f, 58=android.view.AbsSavedState$1@1244c50f, 62=android.view.AbsSavedState$1@1244c50f, 63=android.view.AbsSavedState$1@1244c50f, 64=android.view.AbsSavedState$1@1244c50f, 67=android.view.AbsSavedState$1@1244c50f, 70=android.view.AbsSavedState$1@1244c50f, 72=android.view.AbsSavedState$1@1244c50f, 74=android.view.AbsSavedState$1@1244c50f, 75=android.view.AbsSavedState$1@1244c50f, 78=android.view.AbsSavedState$1@1244c50f, 82=android.view.AbsSavedState$1@1244c50f, 83=android.view.AbsSavedState$1@1244c50f, 86=android.view.AbsSavedState$1@1244c50f, 87=android.view.AbsSavedState$1@1244c50f, 90=android.view.AbsSavedState$1@1244c50f, 92=android.view.AbsSavedState$1@1244c50f, 95=android.view.AbsSavedState$1@1244c50f, 96=android.view.AbsSavedState$1@1244c50f, 97=android.view.AbsSavedState$1@1244c50f, 100=android.view.AbsSavedState$1@1244c50f, 103=android.view.AbsSavedState$1@1244c50f, 104=android.view.AbsSavedState$1@1244c50f, 107=android.view.AbsSavedState$1@1244c50f, 109=android.view.AbsSavedState$1@1244c50f, 110=android.view.AbsSavedState$1@1244c50f, 112=android.view.AbsSavedState$1@1244c50f, 113=android.view.AbsSavedState$1@1244c50f, 114=android.view.AbsSavedState$1@1244c50f, 115=android.view.AbsSavedState$1@1244c50f, 116=android.view.AbsSavedState$1@1244c50f, 117=android.view.AbsSavedState$1@1244c50f, 118=android.view.AbsSavedState$1@1244c50f, 119=android.view.AbsSavedState$1@1244c50f, 120=android.view.AbsSavedState$1@1244c50f, 122=android.view.AbsSavedState$1@1244c50f, 123=android.view.AbsSavedState$1@1244c50f, 124=android.view.AbsSavedState$1@1244c50f, 125=android.view.AbsSavedState$1@1244c50f, 126=android.view.AbsSavedState$1@1244c50f, 128=android.view.AbsSavedState$1@1244c50f, 130=android.view.AbsSavedState$1@1244c50f, 16908290=android.view.AbsSavedState$1@1244c50f}}]}]
D/ReactNativeDebugOutput(22588): MainActivity::onStop()
D/ReactNativeDebugOutput(22588): MainActivity::onDestroy()
D/ReactNativeDebugOutput(22588): MainActivity::onCreate() Bundle[{android:viewHierarchyState=Bundle[mParcelledData.dataSize=5180]}]
D/ReactNativeDebugOutput(22588): MainActivity::onStart()
D/ReactNativeDebugOutput(22588): MainActivity::onRestoreInstanceState() Bundle[{android:viewHierarchyState=Bundle[{android:views={1=android.view.AbsSavedState$1@1244c50f, 4=android.view.AbsSavedState$1@1244c50f, 8=android.view.AbsSavedState$1@1244c50f, 9=android.view.AbsSavedState$1@1244c50f, 13=android.view.AbsSavedState$1@1244c50f, 14=android.view.AbsSavedState$1@1244c50f, 15=android.view.AbsSavedState$1@1244c50f, 16=android.view.AbsSavedState$1@1244c50f, 18=android.view.AbsSavedState$1@1244c50f, 22=android.view.AbsSavedState$1@1244c50f, 25=android.view.AbsSavedState$1@1244c50f, 29=HorizontalScrollView.SavedState{360a9034 scrollPosition=0 isLayoutRtl=true}, 30=android.view.AbsSavedState$1@1244c50f, 32=android.view.AbsSavedState$1@1244c50f, 33=android.view.AbsSavedState$1@1244c50f, 36=android.view.AbsSavedState$1@1244c50f, 38=android.view.AbsSavedState$1@1244c50f, 39=android.view.AbsSavedState$1@1244c50f, 43=android.view.AbsSavedState$1@1244c50f, 45=android.view.AbsSavedState$1@1244c50f, 47=android.view.AbsSavedState$1@1244c50f, 49=android.view.AbsSavedState$1@1244c50f, 50=android.view.AbsSavedState$1@1244c50f, 54=android.view.AbsSavedState$1@1244c50f, 57=android.view.AbsSavedState$1@1244c50f, 58=android.view.AbsSavedState$1@1244c50f, 62=android.view.AbsSavedState$1@1244c50f, 63=android.view.AbsSavedState$1@1244c50f, 64=android.view.AbsSavedState$1@1244c50f, 67=android.view.AbsSavedState$1@1244c50f, 70=android.view.AbsSavedState$1@1244c50f, 72=android.view.AbsSavedState$1@1244c50f, 74=android.view.AbsSavedState$1@1244c50f, 75=android.view.AbsSavedState$1@1244c50f, 78=android.view.AbsSavedState$1@1244c50f, 82=android.view.AbsSavedState$1@1244c50f, 83=android.view.AbsSavedState$1@1244c50f, 86=android.view.AbsSavedState$1@1244c50f, 87=android.view.AbsSavedState$1@1244c50f, 90=android.view.AbsSavedState$1@1244c50f, 92=android.view.AbsSavedState$1@1244c50f, 95=android.view.AbsSavedState$1@1244c50f, 96=android.view.AbsSavedState$1@1244c50f, 97=android.view.AbsSavedState$1@1244c50f, 100=android.view.AbsSavedState$1@1244c50f, 103=android.view.AbsSavedState$1@1244c50f, 104=android.view.AbsSavedState$1@1244c50f, 107=android.view.AbsSavedState$1@1244c50f, 109=android.view.AbsSavedState$1@1244c50f, 110=android.view.AbsSavedState$1@1244c50f, 112=android.view.AbsSavedState$1@1244c50f, 113=android.view.AbsSavedState$1@1244c50f, 114=android.view.AbsSavedState$1@1244c50f, 115=android.view.AbsSavedState$1@1244c50f, 116=android.view.AbsSavedState$1@1244c50f, 117=android.view.AbsSavedState$1@1244c50f, 118=android.view.AbsSavedState$1@1244c50f, 119=android.view.AbsSavedState$1@1244c50f, 120=android.view.AbsSavedState$1@1244c50f, 122=android.view.AbsSavedState$1@1244c50f, 123=android.view.AbsSavedState$1@1244c50f, 124=android.view.AbsSavedState$1@1244c50f, 125=android.view.AbsSavedState$1@1244c50f, 126=android.view.AbsSavedState$1@1244c50f, 128=android.view.AbsSavedState$1@1244c50f, 130=android.view.AbsSavedState$1@1244c50f, 16908290=android.view.AbsSavedState$1@1244c50f}}]}]
D/ReactNativeDebugOutput(22588): MainActivity::onResume()
Second run, after killing the app process with a swipe and restarting the app:
$ adb logcat | grep ReactNativeDebugOutput
D/ReactNativeDebugOutput(24235): MainActivity::onCreate() null
D/ReactNativeDebugOutput(24235): MainActivity::onStart()
D/ReactNativeDebugOutput(24235): MainActivity::onResume()
D/ReactNativeDebugOutput(24235): MainActivity::onPause()
D/ReactNativeDebugOutput(24235): MainActivity::onSaveInstanceState() Bundle[{android:viewHierarchyState=Bundle[{android:views={1=android.view.AbsSavedState$1@205baac5, 4=android.view.AbsSavedState$1@205baac5, 8=android.view.AbsSavedState$1@205baac5, 9=android.view.AbsSavedState$1@205baac5, 13=android.view.AbsSavedState$1@205baac5, 14=android.view.AbsSavedState$1@205baac5, 15=android.view.AbsSavedState$1@205baac5, 16=android.view.AbsSavedState$1@205baac5, 18=android.view.AbsSavedState$1@205baac5, 22=android.view.AbsSavedState$1@205baac5, 25=android.view.AbsSavedState$1@205baac5, 29=HorizontalScrollView.SavedState{e6dec1a scrollPosition=0 isLayoutRtl=false}, 30=android.view.AbsSavedState$1@205baac5, 32=android.view.AbsSavedState$1@205baac5, 33=android.view.AbsSavedState$1@205baac5, 36=android.view.AbsSavedState$1@205baac5, 38=android.view.AbsSavedState$1@205baac5, 39=android.view.AbsSavedState$1@205baac5, 43=android.view.AbsSavedState$1@205baac5, 45=android.view.AbsSavedState$1@205baac5, 47=android.view.AbsSavedState$1@205baac5, 49=android.view.AbsSavedState$1@205baac5, 50=android.view.AbsSavedState$1@205baac5, 54=android.view.AbsSavedState$1@205baac5, 57=android.view.AbsSavedState$1@205baac5, 58=android.view.AbsSavedState$1@205baac5, 62=android.view.AbsSavedState$1@205baac5, 63=android.view.AbsSavedState$1@205baac5, 64=android.view.AbsSavedState$1@205baac5, 67=android.view.AbsSavedState$1@205baac5, 70=android.view.AbsSavedState$1@205baac5, 72=android.view.AbsSavedState$1@205baac5, 74=android.view.AbsSavedState$1@205baac5, 75=android.view.AbsSavedState$1@205baac5, 78=android.view.AbsSavedState$1@205baac5, 82=android.view.AbsSavedState$1@205baac5, 83=android.view.AbsSavedState$1@205baac5, 86=android.view.AbsSavedState$1@205baac5, 87=android.view.AbsSavedState$1@205baac5, 90=android.view.AbsSavedState$1@205baac5, 92=android.view.AbsSavedState$1@205baac5, 95=android.view.AbsSavedState$1@205baac5, 96=android.view.AbsSavedState$1@205baac5, 97=android.view.AbsSavedState$1@205baac5, 100=android.view.AbsSavedState$1@205baac5, 103=android.view.AbsSavedState$1@205baac5, 104=android.view.AbsSavedState$1@205baac5, 107=android.view.AbsSavedState$1@205baac5, 109=android.view.AbsSavedState$1@205baac5, 110=android.view.AbsSavedState$1@205baac5, 112=android.view.AbsSavedState$1@205baac5, 113=android.view.AbsSavedState$1@205baac5, 114=android.view.AbsSavedState$1@205baac5, 115=android.view.AbsSavedState$1@205baac5, 116=android.view.AbsSavedState$1@205baac5, 117=android.view.AbsSavedState$1@205baac5, 118=android.view.AbsSavedState$1@205baac5, 119=android.view.AbsSavedState$1@205baac5, 120=android.view.AbsSavedState$1@205baac5, 122=android.view.AbsSavedState$1@205baac5, 123=android.view.AbsSavedState$1@205baac5, 124=android.view.AbsSavedState$1@205baac5, 125=android.view.AbsSavedState$1@205baac5, 126=android.view.AbsSavedState$1@205baac5, 128=android.view.AbsSavedState$1@205baac5, 130=android.view.AbsSavedState$1@205baac5, 16908290=android.view.AbsSavedState$1@205baac5}}]}]
D/ReactNativeDebugOutput(24235): MainActivity::onStop()
D/ReactNativeDebugOutput(24235): MainActivity::onDestroy()
D/ReactNativeDebugOutput(24235): MainActivity::onCreate() Bundle[{android:viewHierarchyState=Bundle[mParcelledData.dataSize=5180]}]
D/ReactNativeDebugOutput(24235): MainActivity::onStart()
D/ReactNativeDebugOutput(24235): MainActivity::onRestoreInstanceState() Bundle[{android:viewHierarchyState=Bundle[{android:views={1=android.view.AbsSavedState$1@205baac5, 4=android.view.AbsSavedState$1@205baac5, 8=android.view.AbsSavedState$1@205baac5, 9=android.view.AbsSavedState$1@205baac5, 13=android.view.AbsSavedState$1@205baac5, 14=android.view.AbsSavedState$1@205baac5, 15=android.view.AbsSavedState$1@205baac5, 16=android.view.AbsSavedState$1@205baac5, 18=android.view.AbsSavedState$1@205baac5, 22=android.view.AbsSavedState$1@205baac5, 25=android.view.AbsSavedState$1@205baac5, 29=HorizontalScrollView.SavedState{265e472 scrollPosition=0 isLayoutRtl=true}, 30=android.view.AbsSavedState$1@205baac5, 32=android.view.AbsSavedState$1@205baac5, 33=android.view.AbsSavedState$1@205baac5, 36=android.view.AbsSavedState$1@205baac5, 38=android.view.AbsSavedState$1@205baac5, 39=android.view.AbsSavedState$1@205baac5, 43=android.view.AbsSavedState$1@205baac5, 45=android.view.AbsSavedState$1@205baac5, 47=android.view.AbsSavedState$1@205baac5, 49=android.view.AbsSavedState$1@205baac5, 50=android.view.AbsSavedState$1@205baac5, 54=android.view.AbsSavedState$1@205baac5, 57=android.view.AbsSavedState$1@205baac5, 58=android.view.AbsSavedState$1@205baac5, 62=android.view.AbsSavedState$1@205baac5, 63=android.view.AbsSavedState$1@205baac5, 64=android.view.AbsSavedState$1@205baac5, 67=android.view.AbsSavedState$1@205baac5, 70=android.view.AbsSavedState$1@205baac5, 72=android.view.AbsSavedState$1@205baac5, 74=android.view.AbsSavedState$1@205baac5, 75=android.view.AbsSavedState$1@205baac5, 78=android.view.AbsSavedState$1@205baac5, 82=android.view.AbsSavedState$1@205baac5, 83=android.view.AbsSavedState$1@205baac5, 86=android.view.AbsSavedState$1@205baac5, 87=android.view.AbsSavedState$1@205baac5, 90=android.view.AbsSavedState$1@205baac5, 92=android.view.AbsSavedState$1@205baac5, 95=android.view.AbsSavedState$1@205baac5, 96=android.view.AbsSavedState$1@205baac5, 97=android.view.AbsSavedState$1@205baac5, 100=android.view.AbsSavedState$1@205baac5, 103=android.view.AbsSavedState$1@205baac5, 104=android.view.AbsSavedState$1@205baac5, 107=android.view.AbsSavedState$1@205baac5, 109=android.view.AbsSavedState$1@205baac5, 110=android.view.AbsSavedState$1@205baac5, 112=android.view.AbsSavedState$1@205baac5, 113=android.view.AbsSavedState$1@205baac5, 114=android.view.AbsSavedState$1@205baac5, 115=android.view.AbsSavedState$1@205baac5, 116=android.view.AbsSavedState$1@205baac5, 117=android.view.AbsSavedState$1@205baac5, 118=android.view.AbsSavedState$1@205baac5, 119=android.view.AbsSavedState$1@205baac5, 120=android.view.AbsSavedState$1@205baac5, 122=android.view.AbsSavedState$1@205baac5, 123=android.view.AbsSavedState$1@205baac5, 124=android.view.AbsSavedState$1@205baac5, 125=android.view.AbsSavedState$1@205baac5, 126=android.view.AbsSavedState$1@205baac5, 128=android.view.AbsSavedState$1@205baac5, 130=android.view.AbsSavedState$1@205baac5, 16908290=android.view.AbsSavedState$1@205baac5}}]}]
D/ReactNativeDebugOutput(24235): MainActivity::onResume()
(So far, so good.)
In release mode, the results are as described in the Issue Description:
First run:
$ adb logcat | grep ReactNativeDebugOutput
D/ReactNativeDebugOutput(26538): MainActivity::onCreate() null
D/ReactNativeDebugOutput(26538): MainActivity::onStart()
D/ReactNativeDebugOutput(26538): MainActivity::onResume()
D/ReactNativeDebugOutput(26538): MainActivity::onPause()
D/ReactNativeDebugOutput(26538): MainActivity::onSaveInstanceState() Bundle[{android:viewHierarchyState=Bundle[{android:views={1=android.view.AbsSavedState$1@2d5b6cd3, 4=android.view.AbsSavedState$1@2d5b6cd3, 7=android.view.AbsSavedState$1@2d5b6cd3, 8=android.view.AbsSavedState$1@2d5b6cd3, 12=android.view.AbsSavedState$1@2d5b6cd3, 13=android.view.AbsSavedState$1@2d5b6cd3, 14=android.view.AbsSavedState$1@2d5b6cd3, 15=android.view.AbsSavedState$1@2d5b6cd3, 17=android.view.AbsSavedState$1@2d5b6cd3, 20=android.view.AbsSavedState$1@2d5b6cd3, 24=android.view.AbsSavedState$1@2d5b6cd3, 28=HorizontalScrollView.SavedState{2947d010 scrollPosition=0 isLayoutRtl=false}, 29=android.view.AbsSavedState$1@2d5b6cd3, 30=android.view.AbsSavedState$1@2d5b6cd3, 32=android.view.AbsSavedState$1@2d5b6cd3, 35=android.view.AbsSavedState$1@2d5b6cd3, 37=android.view.AbsSavedState$1@2d5b6cd3, 38=android.view.AbsSavedState$1@2d5b6cd3, 42=android.view.AbsSavedState$1@2d5b6cd3, 44=android.view.AbsSavedState$1@2d5b6cd3, 46=android.view.AbsSavedState$1@2d5b6cd3, 48=android.view.AbsSavedState$1@2d5b6cd3, 49=android.view.AbsSavedState$1@2d5b6cd3, 53=android.view.AbsSavedState$1@2d5b6cd3, 56=android.view.AbsSavedState$1@2d5b6cd3, 57=android.view.AbsSavedState$1@2d5b6cd3, 60=android.view.AbsSavedState$1@2d5b6cd3, 62=android.view.AbsSavedState$1@2d5b6cd3, 63=android.view.AbsSavedState$1@2d5b6cd3, 66=android.view.AbsSavedState$1@2d5b6cd3, 69=android.view.AbsSavedState$1@2d5b6cd3, 70=android.view.AbsSavedState$1@2d5b6cd3, 73=android.view.AbsSavedState$1@2d5b6cd3, 74=android.view.AbsSavedState$1@2d5b6cd3, 77=android.view.AbsSavedState$1@2d5b6cd3, 80=android.view.AbsSavedState$1@2d5b6cd3, 82=android.view.AbsSavedState$1@2d5b6cd3, 85=android.view.AbsSavedState$1@2d5b6cd3, 86=android.view.AbsSavedState$1@2d5b6cd3, 89=android.view.AbsSavedState$1@2d5b6cd3, 90=android.view.AbsSavedState$1@2d5b6cd3, 94=android.view.AbsSavedState$1@2d5b6cd3, 95=android.view.AbsSavedState$1@2d5b6cd3, 96=android.view.AbsSavedState$1@2d5b6cd3, 99=android.view.AbsSavedState$1@2d5b6cd3, 102=android.view.AbsSavedState$1@2d5b6cd3, 103=android.view.AbsSavedState$1@2d5b6cd3, 106=android.view.AbsSavedState$1@2d5b6cd3, 108=android.view.AbsSavedState$1@2d5b6cd3, 109=android.view.AbsSavedState$1@2d5b6cd3, 110=android.view.AbsSavedState$1@2d5b6cd3, 112=android.view.AbsSavedState$1@2d5b6cd3, 113=android.view.AbsSavedState$1@2d5b6cd3, 114=android.view.AbsSavedState$1@2d5b6cd3, 115=android.view.AbsSavedState$1@2d5b6cd3, 116=android.view.AbsSavedState$1@2d5b6cd3, 117=android.view.AbsSavedState$1@2d5b6cd3, 118=android.view.AbsSavedState$1@2d5b6cd3, 119=android.view.AbsSavedState$1@2d5b6cd3, 120=android.view.AbsSavedState$1@2d5b6cd3, 122=android.view.AbsSavedState$1@2d5b6cd3, 123=android.view.AbsSavedState$1@2d5b6cd3, 124=android.view.AbsSavedState$1@2d5b6cd3, 125=android.view.AbsSavedState$1@2d5b6cd3, 127=android.view.AbsSavedState$1@2d5b6cd3, 129=android.view.AbsSavedState$1@2d5b6cd3, 16908290=android.view.AbsSavedState$1@2d5b6cd3}}]}]
D/ReactNativeDebugOutput(26538): MainActivity::onStop()
D/ReactNativeDebugOutput(26538): MainActivity::onDestroy()
D/ReactNativeDebugOutput(26538): MainActivity::onCreate() null # <-- HERE'S THE PROBLEM
D/ReactNativeDebugOutput(26538): MainActivity::onStart()
D/ReactNativeDebugOutput(26538): MainActivity::onResume()
Second run, after killing the app process with a swipe in the process manager and restarting the app:
D/ReactNativeDebugOutput(26939): MainActivity::onCreate() null
D/ReactNativeDebugOutput(26939): MainActivity::onStart()
D/ReactNativeDebugOutput(26939): MainActivity::onResume()
D/ReactNativeDebugOutput(26939): MainActivity::onPause()
D/ReactNativeDebugOutput(26939): MainActivity::onSaveInstanceState() Bundle[{android:viewHierarchyState=Bundle[{android:views={1=android.view.AbsSavedState$1@1cea46c2, 4=android.view.AbsSavedState$1@1cea46c2, 7=android.view.AbsSavedState$1@1cea46c2, 8=android.view.AbsSavedState$1@1cea46c2, 12=android.view.AbsSavedState$1@1cea46c2, 13=android.view.AbsSavedState$1@1cea46c2, 14=android.view.AbsSavedState$1@1cea46c2, 15=android.view.AbsSavedState$1@1cea46c2, 17=android.view.AbsSavedState$1@1cea46c2, 20=android.view.AbsSavedState$1@1cea46c2, 24=android.view.AbsSavedState$1@1cea46c2, 28=HorizontalScrollView.SavedState{2d5b6cd3 scrollPosition=0 isLayoutRtl=false}, 29=android.view.AbsSavedState$1@1cea46c2, 30=android.view.AbsSavedState$1@1cea46c2, 32=android.view.AbsSavedState$1@1cea46c2, 35=android.view.AbsSavedState$1@1cea46c2, 37=android.view.AbsSavedState$1@1cea46c2, 38=android.view.AbsSavedState$1@1cea46c2, 42=android.view.AbsSavedState$1@1cea46c2, 44=android.view.AbsSavedState$1@1cea46c2, 46=android.view.AbsSavedState$1@1cea46c2, 48=android.view.AbsSavedState$1@1cea46c2, 49=android.view.AbsSavedState$1@1cea46c2, 53=android.view.AbsSavedState$1@1cea46c2, 56=android.view.AbsSavedState$1@1cea46c2, 57=android.view.AbsSavedState$1@1cea46c2, 60=android.view.AbsSavedState$1@1cea46c2, 62=android.view.AbsSavedState$1@1cea46c2, 63=android.view.AbsSavedState$1@1cea46c2, 66=android.view.AbsSavedState$1@1cea46c2, 69=android.view.AbsSavedState$1@1cea46c2, 70=android.view.AbsSavedState$1@1cea46c2, 73=android.view.AbsSavedState$1@1cea46c2, 74=android.view.AbsSavedState$1@1cea46c2, 77=android.view.AbsSavedState$1@1cea46c2, 80=android.view.AbsSavedState$1@1cea46c2, 82=android.view.AbsSavedState$1@1cea46c2, 85=android.view.AbsSavedState$1@1cea46c2, 86=android.view.AbsSavedState$1@1cea46c2, 89=android.view.AbsSavedState$1@1cea46c2, 90=android.view.AbsSavedState$1@1cea46c2, 94=android.view.AbsSavedState$1@1cea46c2, 95=android.view.AbsSavedState$1@1cea46c2, 96=android.view.AbsSavedState$1@1cea46c2, 99=android.view.AbsSavedState$1@1cea46c2, 102=android.view.AbsSavedState$1@1cea46c2, 103=android.view.AbsSavedState$1@1cea46c2, 106=android.view.AbsSavedState$1@1cea46c2, 108=android.view.AbsSavedState$1@1cea46c2, 109=android.view.AbsSavedState$1@1cea46c2, 110=android.view.AbsSavedState$1@1cea46c2, 112=android.view.AbsSavedState$1@1cea46c2, 113=android.view.AbsSavedState$1@1cea46c2, 114=android.view.AbsSavedState$1@1cea46c2, 115=android.view.AbsSavedState$1@1cea46c2, 116=android.view.AbsSavedState$1@1cea46c2, 117=android.view.AbsSavedState$1@1cea46c2, 118=android.view.AbsSavedState$1@1cea46c2, 119=android.view.AbsSavedState$1@1cea46c2, 120=android.view.AbsSavedState$1@1cea46c2, 122=android.view.AbsSavedState$1@1cea46c2, 123=android.view.AbsSavedState$1@1cea46c2, 124=android.view.AbsSavedState$1@1cea46c2, 125=android.view.AbsSavedState$1@1cea46c2, 127=android.view.AbsSavedState$1@1cea46c2, 129=android.view.AbsSavedState$1@1cea46c2, 16908290=android.view.AbsSavedState$1@1cea46c2}}]}]
D/ReactNativeDebugOutput(26939): MainActivity::onStop()
D/ReactNativeDebugOutput(26939): MainActivity::onDestroy()
D/ReactNativeDebugOutput(26939): MainActivity::onCreate() Bundle[{android:viewHierarchyState=Bundle[mParcelledData.dataSize=5180]}]
D/ReactNativeDebugOutput(26939): MainActivity::onStart()
D/ReactNativeDebugOutput(26939): MainActivity::onRestoreInstanceState() Bundle[{android:viewHierarchyState=Bundle[{android:views={1=android.view.AbsSavedState$1@1cea46c2, 4=android.view.AbsSavedState$1@1cea46c2, 7=android.view.AbsSavedState$1@1cea46c2, 8=android.view.AbsSavedState$1@1cea46c2, 12=android.view.AbsSavedState$1@1cea46c2, 13=android.view.AbsSavedState$1@1cea46c2, 14=android.view.AbsSavedState$1@1cea46c2, 15=android.view.AbsSavedState$1@1cea46c2, 17=android.view.AbsSavedState$1@1cea46c2, 20=android.view.AbsSavedState$1@1cea46c2, 24=android.view.AbsSavedState$1@1cea46c2, 28=HorizontalScrollView.SavedState{18d9a34b scrollPosition=0 isLayoutRtl=true}, 29=android.view.AbsSavedState$1@1cea46c2, 30=android.view.AbsSavedState$1@1cea46c2, 32=android.view.AbsSavedState$1@1cea46c2, 35=android.view.AbsSavedState$1@1cea46c2, 37=android.view.AbsSavedState$1@1cea46c2, 38=android.view.AbsSavedState$1@1cea46c2, 42=android.view.AbsSavedState$1@1cea46c2, 44=android.view.AbsSavedState$1@1cea46c2, 46=android.view.AbsSavedState$1@1cea46c2, 48=android.view.AbsSavedState$1@1cea46c2, 49=android.view.AbsSavedState$1@1cea46c2, 53=android.view.AbsSavedState$1@1cea46c2, 56=android.view.AbsSavedState$1@1cea46c2, 57=android.view.AbsSavedState$1@1cea46c2, 60=android.view.AbsSavedState$1@1cea46c2, 62=android.view.AbsSavedState$1@1cea46c2, 63=android.view.AbsSavedState$1@1cea46c2, 66=android.view.AbsSavedState$1@1cea46c2, 69=android.view.AbsSavedState$1@1cea46c2, 70=android.view.AbsSavedState$1@1cea46c2, 73=android.view.AbsSavedState$1@1cea46c2, 74=android.view.AbsSavedState$1@1cea46c2, 77=android.view.AbsSavedState$1@1cea46c2, 80=android.view.AbsSavedState$1@1cea46c2, 82=android.view.AbsSavedState$1@1cea46c2, 85=android.view.AbsSavedState$1@1cea46c2, 86=android.view.AbsSavedState$1@1cea46c2, 89=android.view.AbsSavedState$1@1cea46c2, 90=android.view.AbsSavedState$1@1cea46c2, 94=android.view.AbsSavedState$1@1cea46c2, 95=android.view.AbsSavedState$1@1cea46c2, 96=android.view.AbsSavedState$1@1cea46c2, 99=android.view.AbsSavedState$1@1cea46c2, 102=android.view.AbsSavedState$1@1cea46c2, 103=android.view.AbsSavedState$1@1cea46c2, 106=android.view.AbsSavedState$1@1cea46c2, 108=android.view.AbsSavedState$1@1cea46c2, 109=android.view.AbsSavedState$1@1cea46c2, 110=android.view.AbsSavedState$1@1cea46c2, 112=android.view.AbsSavedState$1@1cea46c2, 113=android.view.AbsSavedState$1@1cea46c2, 114=android.view.AbsSavedState$1@1cea46c2, 115=android.view.AbsSavedState$1@1cea46c2, 116=android.view.AbsSavedState$1@1cea46c2, 117=android.view.AbsSavedState$1@1cea46c2, 118=android.view.AbsSavedState$1@1cea46c2, 119=android.view.AbsSavedState$1@1cea46c2, 120=android.view.AbsSavedState$1@1cea46c2, 122=android.view.AbsSavedState$1@1cea46c2, 123=android.view.AbsSavedState$1@1cea46c2, 124=android.view.AbsSavedState$1@1cea46c2, 125=android.view.AbsSavedState$1@1cea46c2, 127=android.view.AbsSavedState$1@1cea46c2, 129=android.view.AbsSavedState$1@1cea46c2, 16908290=android.view.AbsSavedState$1@1cea46c2}}]}]
D/ReactNativeDebugOutput(26939): MainActivity::onResume()
I think this'll happen when you set the activity:launchMode to standard (in AndroidManifest.xml).
Try to change the launchMode to SingleTask & see if it fixes your problem.
Might be related: https://github.com/facebook/react-native/issues/7079
Thanks @sbycrosz! I just tried that and unfortunately it made the problem worse, it happened even on the second try after swipe-killing the app. Tried the other launchModes as well but no joy. Appreciate the input though, reading through all this helps to understand the overall Activity picture a bit better.
We were observing the exact same issue on RN 0.35.0 on every Android version we tested (4.x - 6.x) in both release and debug modes. As implied by https://github.com/facebook/react-native/issues/7079 and https://github.com/facebook/react-native/issues/8570, what's happening here is that multiple MainActivity instances are being pushed when the app backgrounds and then foregrounds again from a fresh install or upgrade. Both activities then receive AppState change events although only the top one is presenting to the user. Every time you background and foreground in this state, another MainActivity is pushed on top of the older ones. We also observed that killing and restarting the app would fix the issue until the next reinstall/upgrade.
You can see the multiple activities by dumping the activity stack. We also worked around this by setting android:launchMode="singleInstance" in our Manifest, although singleTask sounded like it would work as well.
Overall I think this is definitely a RN-level bug, as from the perspective of JS app code, you should be able to make a reasonable expectation that multiple instances of your app will not be launched inside the same Android task. At the very least I think the RN AndroidManifest.xml template should include a reasonable default set for launchMode as either singleInstance or singleTask. However this does seem like a workaround for an issue that should probably be solved comprehensively by the RN architecture in some manner.
We also face the same problem on RN 0.32 and Android 5.1. However, the issue is reproduced only on Xiaomi and DOOGEE devices, but it seems OK on Samsung.
If our app is built and run locally, the issue is not reproduced, despite debug or release mode. To reproduce the issue I have to deploy an apk to Google Play and install on a device. And after install on the first run the issue can be observed when switching between background and foreground modes.
Setting launchMode to singleInstance in AndroidManifest.xml for the MainActivity fixed the problem.
Thanks everyone for the solution.
P.S. Latest RN 0.37 has the issue.
+1,RN v0.37 face the same porblem, even the empty project created by 'react-native init'.
Setting launchMode seems fixed the problem, but I doubt if any other issue would be caused.
Looking forward the official solution.
Basically echoing what has been said here, singleInstance fixes it. But I am unsure from reading about launchMode in Android if this has any negative consequences for RN.
Would almost be interesting to submit a PR with android:launchMode="singleInstance" as the default in the react-native init template, just to see what the core contributors has to say about this.
Interesting note from the docs:
The "singleTask" and "singleInstance" modes also differ from each other in only one respect: A "singleTask" activity allows other activities to be part of its task. It's always at the root of its task, but other activities (necessarily "standard" and "singleTop" activities) can be launched into that task. A "singleInstance" activity, on the other hand, permits no other activities to be part of its task. It's the only activity in the task. If it starts another activity, that activity is assigned to a different task — as if FLAG_ACTIVITY_NEW_TASK was in the intent.
@cbrevik Yes, a PR is a good idea, although I'm still unclear as to whether singleInstance or singleTask is a better default. singleInstance has been working well for us so far, but I wonder if there are any native libraries out there that would depend on the behavior allowed by singleTask?
@fadookie I've wondered about the same thing. I've tried to read up on it, but I can't find a definitive answer to that question.
Since singleTask and singleInstance achieves the same goal (only one instance of our MainActivity allowed on the device), it seems like singleTask would be a better default.
At the same time, we're probably masking an underlying problem with RN with this fix. It'd be nice to have the core contributors weigh in on this issue.
Closing this issue because it has been inactive for a while. If you think it should still be opened let us know why.
When I get time I might make a PR to change the template to one of the
defaults discussed above. Still not sure which one is better though.
On Wed, Jun 14, 2017, 3:06 PM Facu Escobar notifications@github.com wrote:
@hramos https://github.com/hramos I've seen a few issues related to
this bug, and none of them has been fixed or taken by RN developers to fix
it.can you guys stop closing issues by inactivity and start to fix them?
I am handling the same issue, I've tried all the options I've seen in all
closed issues, and different articles, but none of them fixed my problem.This is a real issue, you guys should take a deeper look here.
Cheers.—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/facebook/react-native/issues/10266#issuecomment-308571668,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAGwrDKlOh6AifqnHkVMu-Zt5zrR23ryks5sEFlsgaJpZM4KPZcU
.
Most helpful comment
We were observing the exact same issue on RN 0.35.0 on every Android version we tested (4.x - 6.x) in both release and debug modes. As implied by https://github.com/facebook/react-native/issues/7079 and https://github.com/facebook/react-native/issues/8570, what's happening here is that multiple
MainActivityinstances are being pushed when the app backgrounds and then foregrounds again from a fresh install or upgrade. Both activities then receiveAppStatechange events although only the top one is presenting to the user. Every time you background and foreground in this state, anotherMainActivityis pushed on top of the older ones. We also observed that killing and restarting the app would fix the issue until the next reinstall/upgrade.You can see the multiple activities by dumping the activity stack. We also worked around this by setting
android:launchMode="singleInstance"in our Manifest, althoughsingleTasksounded like it would work as well.Overall I think this is definitely a RN-level bug, as from the perspective of JS app code, you should be able to make a reasonable expectation that multiple instances of your app will not be launched inside the same Android task. At the very least I think the RN
AndroidManifest.xmltemplate should include a reasonable default set forlaunchModeas eithersingleInstanceorsingleTask. However this does seem like a workaround for an issue that should probably be solved comprehensively by the RN architecture in some manner.