-
Notifications
You must be signed in to change notification settings - Fork 24.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Android] BackAndroid 'hardwareBackPress' event not working #3223
Comments
I had to add the following to @Override
public void onBackPressed() {
if (mReactInstanceManager != null) {
mReactInstanceManager.onBackPressed();
} else {
super.onBackPressed();
}
} |
@satya164 your code works! |
@satya164 Thank's a lot, it works. |
@vincelwt It was absent from the boilerplate app previously. I believe it has been added. |
Yes, the back button handler will be added to all new apps by Closing this on as @satya164 provided the correct solution for existing apps. Thanks for reporting! |
Hi I have included the code snippet in MainActivity. But Here is my observation: When the app loads and the first scene is rendered, here when i press the hardware back button, the app quits because I am returning false from my implementation of BackAndroid. But when I move to the second scene and again when I come back to the first scene and then press the hardware back button, the app does not quit. Is this the default expected behaviour? My implementation is as follows: Another Observation is: @satya164 @mkonicek Any comments? Thanks in Advance |
I have included code, and I got
|
@TeodorKolev So do I, any solution? |
I have a question here. If I add these code in MainActivity:
Did I need to add BackAndroid Listener in JS? Maybe just leave one of them? Any suggestions? |
mReactInstanceManager is private. So I can not add this to MainActivity |
@TeodorKolev you need import this package in file: import com.facebook.react.ReactActivity;
import com.facebook.react.ReactInstanceManager;
public class MainActivity extends ReactActivity {
private ReactInstanceManager mReactInstanceManager;
[...]
@Override
public void onBackPressed() {
if (mReactInstanceManager != null) {
mReactInstanceManager.onBackPressed();
} else {
super.onBackPressed();
}
} |
Leaving for any posterity... I am on v0.46.0 of react-native and had the same issue. I tracked the issue down to this file in the react-native code base When running with the chrome debugger turned off the line
always returns an empty array for After more investigation, I think the issue was discovered and discussed in the following PR #15182. Even after copy/pasting the PR change in an older version of RN it did not work most likely caused by the issue described in the PR. After some very slight modifications I got it working by changing to RCTDeviceEventEmitter.addListener(DEVICE_BACK_EVENT, function() {
var invokeDefault = true;
var subscriptions = []
_backPressSubscriptions.forEach(sub => subscriptions.push(sub))
for (var i = 0; i < subscriptions.reverse().length; ++i) {
if (subscriptions[i]()) {
invokeDefault = false;
break;
}
}
if (invokeDefault) {
BackHandler.exitApp();
}
}); Simply using a So you could fork react-native and use a modified version, submit a PR though I imagine that will take a little while to be approved and merged upstream, or you can do something similar to what I did which was to override the // other imports
import { BackHandler, DeviceEventEmitter } from 'react-native'
class MyApp extends Component {
constructor(props) {
super(props)
this.backPressSubscriptions = new Set()
}
componentDidMount = () => {
DeviceEventEmitter.removeAllListeners('hardwareBackPress')
DeviceEventEmitter.addListener('hardwareBackPress', () => {
let invokeDefault = true
const subscriptions = []
this.backPressSubscriptions.forEach(sub => subscriptions.push(sub))
for (let i = 0; i < subscriptions.reverse().length; i += 1) {
if (subscriptions[i]()) {
invokeDefault = false
break
}
}
if (invokeDefault) {
BackHandler.exitApp()
}
})
this.backPressSubscriptions.add(this.handleHardwareBack)
}
componentWillUnmount = () => {
DeviceEventEmitter.removeAllListeners('hardwareBackPress')
this.backPressSubscriptions.clear()
}
handleHardwareBack = () => { /* do your thing */ }
render() { return <YourApp /> }
} |
I cannot overstate how much you just saved my life on this @austenLacy |
@austenLacy your solution worked like a charm! thanks a ton for your great comment! |
@austenLacy Your solution worked for me. Thank you. |
@austenLacy, you da bomb! |
still a problem, React Native team please fix this ASAP, I'm using expo so won't be able to modify android folder :( |
I upgraded my RN version to 0.55.4 from 0.52 , initially backhandler was working perfectly but after upgrade it stopped listening. |
Hi, I found this is a bug of var set = new Set()
set.add('a')
console.warn(set.has('a'))
console.warn(Array.from(set.values())) In node interpreter the output is |
I solved it, just add the polyfill for require('core-js/es6/array')
export default App {
// ...
} |
BackAndroid imported with :
-> still quit.
On the docs, it says if it return true, app should not quit.
Here is an extremely minified version of my app : https://rnplay.org/apps/Ss8E8Q
On the demo, it says "unfortunately, the app has stopped."
On my phone, it says nothing.
If it can helps:
Tried using LG G2 on CloudyG2 with 5.0.2.
Will try on Nexus 5 (5.1.1) and genymotion later.
The text was updated successfully, but these errors were encountered: