react-native-webview: Android is crashing when "WebView" is wrapped by "View"
Bug description: I have an autosized webview that works perfectly on ios:
import React, { useState } from "react";
import { View } from "react-native";
import { WebView } from "react-native-webview";
import PropTypes from "prop-types";
const BODY_TAG_PATTERN = /<\/ *body>/;
const code = `
<style>
body, html {
margin: 0;
padding: 0;
}
</style>
<script>
window.ReactNativeWebView.postMessage(document.body.scrollHeight, '*');
</script>
`;
const injectCode = (html) => {
return html.replace(BODY_TAG_PATTERN, `${code}</body>`);
};
const WebViewAutoHeight = ({ html, style }) => {
const [contentHeight, setContentHeight] = useState(1);
const adjustHeight = (event) => {
setContentHeight(parseInt(event.nativeEvent.data));
};
if (!html) {
throw new Error("At this moment, WebViewAutoHeight only supports html files");
}
if (!BODY_TAG_PATTERN.test(html)) {
throw new Error(`Cannot find </body> from: ${html}`);
}
return (
<View style={[style, { height: contentHeight }]}>
<WebView
source={{ html: injectCode(html) }}
onMessage={adjustHeight}
/>
</View>
);
};
WebViewAutoHeight.propTypes = {
html: PropTypes.string.isRequired,
style: PropTypes.any
};
WebViewAutoHeight.defaultProps = {
style: null
};
export default WebViewAutoHeight;
However, when I try to use it on android, the app crashes without a message. Then I decided to remove everything and replaced the render method with the following:
<View>
<WebView
source={{ uri: 'https://infinite.red' }}
style={{ marginTop: 20 }}
/>
</View>
but it was still crashing. Then I removed the outer view element and it worked!
Expected behavior: The android app should not crash
Environment:
- OS: macOS Mojave
- OS version: 10.14.5
- react-native version: 0.59.8
- react-native-webview version: 6.9.0
About this issue
- Original URL
- State: closed
- Created 5 years ago
- Reactions: 6
- Comments: 40 (1 by maintainers)
Commits related to this issue
- fix: [IOAPPFD0-50] Crash when navigating out of a WebView on Android (#4460) ## Short description This PR implements a workaround for a potential crash that could occur when navigating out of a scr... — committed to pagopa/io-app by LazyAfternoons a year ago
- fix: occasional Android crash - Fix suggested here: - https://github.com/react-native-webview/react-native-webview/issues/811#issuecomment-748611465 - Docs on renderToHardwareTextureAndroid: - ht... — committed to High5Apps/react-native-vis-network by High5Apps a year ago
Just spent far too long working on a solution for this. I didn’t get any of the above solutions to work, however setting
androidHardwareAccelerationDisabled={true}on the WebView did work.@Rendfold I managed to come across this link in my research: https://www.gitmemory.com/issue/react-native-community/react-native-webview/430/493976111
Apperently this bug can be fixed by changing the Opacity of the webviwe to 0.99 instead of the default value of 1. Setting the overflow value to “hidden” prevents that the background will be visible.
This worked for me as a fix Altho the androud crash did only appeare when I pressed the back button and by this dismissed the screen. I am also using react navigation which probably played a role as well.
In my case, I fixed it by adding
renderToHardwareTextureAndroid={true}on it’s parent View.I had the same issue and it worked to set the opacity to 0.99 - Absolutely ridiculous that this works however, makes absolutely no sense.
We use a hidden webview in our authentication process. After logging in, we navigate the user to another screen. Then we get this crash on android. We are using react-navigation v5.
We were already using the
androidHardwareAccelerationDisabledprop fix until upgrading React Native from 63 to 66.At v66, none of the above solutions in this issue worked. However, we noticed that our wrapper
componentWillUnmountlifecycle method wasn’t getting called.So our solution was to have our parent screen component listen to react-navigation events:
transitionEnd&blurto keep ahasNavigationTransitionedboolean:Then, use that boolean to conditionally render the WebView:
I think this resolves some race condition, and allows the webview to be properly disposed on android.
@jonsaich and @pmm1 solutions work for me but i prefer
androidHardwareAccelerationDisabled={true}. Less error prone, some developer can be confused about the opacity solution and accidentaly remove it…Updating: well
androidHardwareAccelerationDisabled={true}has a huge trade-off in perfomance in my case, now i’m using the opacity solution…I’m on 11.13.0 and none of these fixes work 😢 I see this issue was closed but I don’t see any real resolved issue with it? The opacity fix and hardwareAcceleration fix don’t work, neither does disabling animation on the react navigation screen…
Using
androidLayerType="software"solves the problem, but performance becomes horrible this way. Another workaround is to unmount the webview when leaving the screen, but this comes with its own problems.Can confirm that applying styles
{ opacity: 0.99, overflow: 'hidden' }to the WebView fixed this issue for me.androidHardwareAccelerationDisabled={true}stopped the crashing but the video was black. You could press the play button but not see the video at all.Very peculiar…
What was the solution?
opacity=0.99or react-navigationanimationEnabled=falseworks for me.androidLayerType="software"has a very bad impact on performances.Thanks @BDDev the solution works This should be a big problem to address, crash still happen in 2023
I have the same issue and tried all the mentionned solutions, but only the androidLayerType=“software” shared by @Tracer1337 worked. Thanks!
WebView with style={{ opacity: 0.99, overflow: ‘hidden’ }} worked for me too, thanks for this thread!
Solved by using flex:1 in View and WebView style.
using
androidLayerType="software"orandroidHardwareAccelerationDisabled={true}seem to fix it,However that seems to cause issues when trying to render 3d objects inside the webview.
Workaround was to hide the webview component while the screen is loading. And show it after a 500ms delay.
My uneducated guess is that it might be something to do with the screen animation when it enters the view.
setting
style={{ opacity: 0.99, overflow: 'hidden' }}on the webview fixes the crash on android for us as wellI managed to fix this by setting view style to, webview ^11.17.1
In our case,
androidHardwareAccelerationDisabled={true}worked, whileopacity: 0.99did not. We have had to apply this fix to all webviews in our app. This issue was easiest to reproduce on LG Stylo 6 and Google Pixel devices.This is what worked for us with the least perf hit. Thanks @sooakim!
For those who are big suffered by this problem! I’ve tried all of the above remedies, but none of them work in RN 0.69 and React Navigation 6. So I’ve used “transitionEnd” event of React Navigation, I’ve solved this. Below is my worked code.
// React component class file constructor(props) { super(props) this.state = { isWebViewLoaded: false, }
props.navigation.addListener(‘transitionEnd’, () => { this.setState({ isWebViewLoaded: true }) })
props.navigation.addListener(‘beforeRemove’, () => { this.setState({ isWebViewLoaded: false }) }) }
render() { return ( <View style={{ flex: 1, position: ‘relative’ }}> {this.state.isWebViewLoaded && ( <WebView source={{ uri: ‘https://google.com/’, headers: { ‘Cache-Control’: ‘no-cache’ }, }} renderError={() => { return ( <View style={{ flex: 1, alignItems: ‘center’, justifyContent: ‘center’, }}
Network connection error.
) }} /> )}
)
// package.json file “@react-navigation/native”: “^6.0.11”, “@react-navigation/native-stack”: “^6.7.0”, “@react-navigation/stack”: “^6.2.2”, “react”: “18.2.0”, “react-native”: “0.69.1”, “react-native-gesture-handler”: “^2.5.0”, “react-native-screens”: “^3.15.0”, “react-native-webview”: “^11.22.7”
Thank you, its work, save my time.