When rendering iframes with <HTML />, Android crashes while navigating back to stack screen

6.1k views Asked by At

When enabling screens in react-native-screens, and having a screen which renders an <HTML /> component passed with an iframe HTML element, the app crashes while pressing the back button to return to the home screen. Full reproduction here.

Environment

  • React Native: 0.61.5
  • react-native-render-html: 4.2.2
  • react-native-webview: 10.3.2
  • react-native-screens: 2.8.0
  • react-native-render-html-table-bridge: 0.6.1

Crash log

07-29 17:41:49.173  6901  6901 F crashpad: dlopen: dlopen failed: library "libandroidicu.so" not found: needed by /system/lib/libharfbuzz_ng.so in namespace (default)
--------- beginning of crash
07-29 17:41:49.176  6410  6441 F libc    : Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x1c in tid 6441 (RenderThread), pid 6410 (com.newmednav)
07-29 17:41:49.340  6904  6904 F DEBUG   : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
07-29 17:41:49.340  6904  6904 F DEBUG   : Build fingerprint: 'google/sdk_gphone_x86_arm/generic_x86_arm:11/RPB2.200611.009/6625208:userdebug/dev-keys'
07-29 17:41:49.340  6904  6904 F DEBUG   : Revision: '0'
07-29 17:41:49.340  6904  6904 F DEBUG   : ABI: 'x86'
07-29 17:41:49.340  6904  6904 F DEBUG   : Timestamp: 2020-07-29 17:41:49+0545
07-29 17:41:49.340  6904  6904 F DEBUG   : pid: 6410, tid: 6441, name: RenderThread  >>> com.newmednav <<<
07-29 17:41:49.340  6904  6904 F DEBUG   : uid: 10152
07-29 17:41:49.340  6904  6904 F DEBUG   : signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x1c
07-29 17:41:49.340  6904  6904 F DEBUG   : Cause: null pointer dereference
07-29 17:41:49.340  6904  6904 F DEBUG   :     eax efbc2cb0  ebx eed5c69c  ecx eed52a80  edx 00000000
07-29 17:41:49.341  6904  6904 F DEBUG   :     edi d139ae90  esi 00000000
07-29 17:41:49.341  6904  6904 F DEBUG   :     ebp c086ed48  esp c086eb50  eip ee698c1c
07-29 17:41:49.425  6904  6904 F DEBUG   : backtrace:
07-29 17:41:49.425  6904  6904 F DEBUG   :       #00 pc 00247c1c  /system/lib/libhwui.so (android::uirenderer::skiapipeline::GLFunctorDrawable::onDraw(SkCanvas*)+1548) (BuildId: 434a9b68672e1dd2b15599730362463d)
07-29 17:41:49.425  6904  6904 F DEBUG   :       #01 pc 00303a57  /system/lib/libhwui.so (SkDrawable::draw(SkCanvas*, SkMatrix const*)+87) (BuildId: 434a9b68672e1dd2b15599730362463d)
07-29 17:41:49.425  6904  6904 F DEBUG   :       #02 pc 002f4606  /system/lib/libhwui.so (SkBaseDevice::drawDrawable(SkDrawable*, SkMatrix const*, SkCanvas*)+38) (BuildId: 434a9b68672e1dd2b15599730362463d)
07-29 17:41:49.425  6904  6904 F DEBUG   :       #03 pc 00659291  /system/lib/libhwui.so (SkGpuDevice::drawDrawable(SkDrawable*, SkMatrix const*, SkCanvas*)+353) (BuildId: 434a9b68672e1dd2b15599730362463d)
07-29 17:41:49.425  6904  6904 F DEBUG   :       #04 pc 002d9dc0  /system/lib/libhwui.so (SkCanvas::onDrawDrawable(SkDrawable*, SkMatrix const*)+48) (BuildId: 434a9b68672e1dd2b15599730362463d)
7

There are 7 answers

0
Gyan Prakash On BEST ANSWER

The updated solution for this is androidLayerType="software", since androidHardwareAccelerationDisabled is now deprecated.

ex:-

<AutoHeightWebView
   androidHardwareAccelerationDisabled // update here androidLayerType="software"
   ...
/>
1
Jules Sam. Randolph On

This was caused by an incompatibility between react-native-webview and react-native-screens, which you must depend on if you are using @react-navigation/* packages.

EDIT: there seems to have been a regression since. It's being tracked here.

Fixed in [email protected]

See CHANGELOG in https://github.com/software-mansion/react-native-screens/releases/tag/2.12.0

If you can't upgrade react-native-screens

There are 3 workarounds:

WebView opacity

const tagsStyles = {
    iframe: {
        opacity: 0.99
    },
    // If you are using @native-html/table-plugin
    table: {
        opacity: 0.99
    }
}

And use this prop when rendering:

return <HTML tagsStyles={tagsStyles} ... />

Disabling hardware acceleration

In android/app/src/main/AndroidManifest.xml:

<activity
  android:hardwareAccelerated="false"
/>

Disabling native screens

From your App.js file:

// import {enableScreens} from 'react-native-screens';

// enableScreens();
0
Manil Malla On

Disabling the navigation animation for the screen worked for me. I just added the animation: 'none', screen option for the navigator, as shown below.

const StackNavigator = props => {
  return (
    <Stack.Navigator  
      screenOptions={{
        animation: 'none', // <-- Add this.
      }}
    >
      // ...
    </Stack.Navigator>
  );
};

P.S.: I also tried other options like

  1. Setting the opacity of the WebView to 0.99.
  2. Setting the renderToHardwareTextureAndroid={true} for the parent View of the WebView.
  3. Setting the androidLayerType property of the WebView to "software".
  4. Disabling hardware acceleration in android/app/src/main/AndroidManifest.xml's <activity> by setting android:hardwareAccelerated="false".

1 and 2 were not useful and 3 and 4 while useful, also tended to cause only the audio to play and displayed a blank black screen.

Thus I found setting the animation: 'none', screen option for the navigator to be most useful. This is the iFrame I used

<iframe 
  width="853" 
  height="480" 
  src="https://www.youtube.com/embed/jbnUQ-o381k" 
  title="WAI WAI QUICK PYRO COMEDY CLUB WITH CHAMPIONS | EPI 52 | Bijay Baral, Bhola Raj Sapkota" 
  frameborder="0" 
  allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
  allowfullscreen
></iframe>
1
John Stuart On

Another workaround is to add androidLayerType: 'software' in webViewProps inside htmlProps which pass to render HTML table as mentioned below.

const webViewProps = {
    androidLayerType: 'software',
  }

  const htmlProps = {
    WebView,
    renderers: {
      table: TableRenderer,
    },
    renderersProps: {
      table: {
        cssRules,
        webViewProps,
        computeContainerHeight() {
          return null
        },
      },
    },
    customHTMLElementModels: {
      table: tableModel,
    },
  }

https://github.com/react-navigation/react-navigation/issues/6960#issuecomment-587418809

0
Patrick Albrecht On

I was struggling with this problem for a very long time. It seems the problem is when the iframe gets rendered while the animation from the stack.navigation is still in progress. For me the simplest solution was to block the iframe from rendering till the animation of the navigation has finished. The stack.navigator has a event for this.(transitionEnd). To achieve this you can simply do some thing like this:

const [finishedTransition, setFinishedTransition] = setState(false)
React.useEffect(() => {
  const unsubscribe = navigation.addListener('transitionEnd', (e) => {
    setFinishedTransition(true)
  });

  return unsubscribe;
}, [navigation]);
return(
  <>
      {finishedTransition ? <Html with iframe/> : null}
  </>
)
0
Gregory Galushka On

One more fix is to disable animation for react-navigation in navigationOptions.

static navigationOptions = () => ({
  animationEnabled: false,
});
0
Florin Dobre On

For me the error was triggered by social media iframes. Applying style = {{ opacity: 0.99 }} was the only thing that worked for me:

 <WebView
    useWebKit={true}
    scrollEnabled={false}
    scalesPageToFit={true}
    source={{ html: html }}
    javaScriptEnabled={true}
    bounces={false}
    overScrollMode={'never'}
    pagingEnabled={true}
    style={{ opacity: 0.99 }} //<---------
 />

Source: https://github.com/react-native-webview/react-native-webview/issues/811