Why does my React Native Android app crash when closed or the Back button is pressed?

Viewed 3179

My React Native Android application crashes when the app closes or when the Back button is pressed. It seems if the app exits using the Back button or not the app reports a crash.

I've searched through many similar issues and solutions and none have worked for me.

I can disable the Back button completely but that will irritate users not being able to close the app.

I tried "react-native-exit-app" which apparently should close an app without invoking a crash notification but that doesn't work. It still reports a crash on exit.

I have tried BackHandler.exitApp() but that also exits the app with a crash.

I am using React Navigation and I can see the Back button controls routes. I thought maybe that might be causing the issue so I tried to disable that. So not have the Back button control routes. I managed to disable it but not sure if it was done correctly. Even so it didn't help as the app still crashes on Back or exit.

I am using Redux as well. I read somewhere that it may cause issues with the Back button. I can't see how though. I have not tried any Redux fixes as I am not sure how Redux can cause a problem with this.

I have a timer in my app to run an event every 1 minute. I wondered if maybe that could be causing an issue?

When the app crashes it doesn't say anything useful in the logs. It just has one line which is not specific.

I'm a bit stuck now. I am seeing loads of reported crashes in the Play Store. I know it is from people pressing the Back button and then opening the app again. I need to find a solution but I have tried everything and no luck.

Any ideas?

--- CODE

import { BackHandler, ToastAndroid } from 'react-native';

constructor(properties) {
  super(properties);

  this.handleBackButton = this.handleBackButton.bind(this);
}

componentWillMount() {
  BackHandler.addEventListener('hardwareBackPress', this.handleBackButton);
}

componentWillUnmount() {
  BackHandler.removeEventListener('hardwareBackPress', this.handleBackButton);
}

handleBackButton = () => {
  console.log('Android hardware back button pressed!');
  ToastAndroid.show('Exiting the app...', ToastAndroid.SHORT);
  BackHandler.exitApp();
  return true;
}

-- LOG

07-04 12:13:50.893 10849 10904 I ReactNativeJS: Android hardware back button pressed!
07-04 12:13:50.895 10849 10904 I ReactNativeJS: Android hardware back button pressed!
07-04 12:13:50.948 10849 10904 I ReactNativeJS: 'appState', 'background'
07-04 12:13:51.641 10849 10849 D ReactNative: ReactInstanceManager.detachViewFromInstance()   <---   this is all I see when it crashes

-- UPDATE

I managed to get a stack trace working like this...

cd android
./gradlew installDebug --stacktrace
cd ..
react-native log-android

It looks like Firebase is what is crashing...

07-04 13:55:55.362 13517 13574 W ReactNativeJS: Overwriting FirebaseError base field "name" can cause unexpected behavior.
07-04 13:55:55.434 13517 13574 W ReactNativeJS: Overwriting FirebaseError base field "name" can cause unexpected behavior.
07-04 13:55:55.493 13517 13574 E ReactNativeJS: [DEFAULT]: Firebase: Firebase App named '[DEFAULT]' already exists (app/duplicate-app).
07-04 13:55:55.493 13517 13574 E ReactNativeJS: 
07-04 13:55:55.493 13517 13574 E ReactNativeJS: This error is located at:
07-04 13:55:55.493 13517 13574 E ReactNativeJS:     in Wrapper (at renderApplication.js:35)
07-04 13:55:55.493 13517 13574 E ReactNativeJS:     in RCTView (at View.js:45)
07-04 13:55:55.493 13517 13574 E ReactNativeJS:     in View (at AppContainer.js:98)
07-04 13:55:55.493 13517 13574 E ReactNativeJS:     in RCTView (at View.js:45)
07-04 13:55:55.493 13517 13574 E ReactNativeJS:     in View (at AppContainer.js:115)
07-04 13:55:55.493 13517 13574 E ReactNativeJS:     in AppContainer (at renderApplication.js:34)
07-04 13:55:55.550 13517 13574 E ReactNativeJS: [DEFAULT]: Firebase: Firebase App named '[DEFAULT]' already exists (app/duplicate-app).

--- SOLVED!

Checking the stack trace was really helpful. Once I got that working I saw it was Firebase causing the problem.

I resolved the issue like this:

if (!firebase.apps.length) {
  firebase.initializeApp({
    ...
  });
}
1 Answers

Are you removing the event listener when your component unmounts. Most routing libraries will re-mount the view, causing a new listener to be added and if that happens, the application might glitch or even crash.

componentDidMount() {
    this.backHandler = BackHandler.addEventListener('hardwareBackPress', () => {
        if (!this.shouldBeAppClosed()) {
            this.yourBackButtonFunction();
            return true;
        }
        return false;
    });
}

componentWillUnmount() {
    this.backHandler.remove();
}
Related