使用 <HTML /> 渲染 iframe 时,Android 在导航回堆栈屏幕时崩溃

问题描述 投票:0回答:8

react-native-screens
中启用屏幕,并且具有渲染通过
<HTML />
HTML 元素传递的
iframe
组件的屏幕时,应用程序会在按后退按钮返回主屏幕时崩溃。 完整再现在这里

环境

  • 反应本机:0.61.5
  • react-native-render-html:4.2.2
  • react-native-webview:10.3.2
  • 反应本机屏幕:2.8.0
  • react-native-render-html-table-bridge:0.6.1

崩溃日志

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)
react-native react-native-render-html
8个回答
10
投票

这是由于

react-native-webview
react-native-screens
之间不兼容造成的,如果您使用
@react-navigation/*
软件包,则必须依赖它。

编辑:此后似乎出现了回归。 这里正在追踪

已修复
[email protected]

请参阅变更日志https://github.com/software-mansion/react-native-screens/releases/tag/2.12.0

如果无法升级react-native-screens

有 3 种解决方法:

WebView 不透明度

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

并在渲染时使用此道具:

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

禁用硬件加速

android/app/src/main/AndroidManifest.xml

<activity
  android:hardwareAccelerated="false"
/>

禁用本机屏幕

来自您的

App.js
文件:

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

// enableScreens();

6
投票

另一个修复是在 navigationOptions 中禁用反应导航动画。

static navigationOptions = () => ({
  animationEnabled: false,
});

1
投票

另一个解决方法是在

androidLayerType: 'software'
内的
webViewProps 
中添加
htmlProps
,它会传递到渲染 HTML 表,如下所述。

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
投票

此问题的更新解决方案是 androidLayerType="software",因为 androidHardwareAccelerationDisabled 现已弃用。

例如:-

<AutoHeightWebView
   androidHardwareAccelerationDisabled // update here androidLayerType="software"
   ...
/>

0
投票

对我来说,错误是由社交媒体 iframe 触发的。 申请

style = {{ opacity: 0.99 }}
是唯一对我有用的事情:

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

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


0
投票

禁用屏幕的导航动画对我有用。我刚刚为导航器添加了

animation: 'none',
屏幕选项,如下所示。

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

P.S.:我还尝试了其他选项,例如

  1. opacity
    WebView
    设置为
    0.99
  2. renderToHardwareTextureAndroid={true}
    设置为
    View
    的父级
    WebView
  3. androidLayerType
    WebView
    属性设置为
    "software"
  4. 通过设置<activity>来禁用
    android/app/src/main/AndroidManifest.xml
    android:hardwareAccelerated="false"
    中的硬件加速。

1 和 2 没有用,3 和 4 虽然有用,但也往往会导致仅播放音频并显示空白黑屏。

因此,我发现为导航器设置

animation: 'none',
屏幕选项是最有用的。 这是我使用的iFrame

<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>

0
投票

我在这个问题上挣扎了很长时间。问题似乎出在 iframe 渲染时,而 stack.navigation 中的动画仍在进行中。 对我来说,最简单的解决方案是阻止 iframe 渲染,直到导航动画完成。 stack.navigator 有一个与此相关的事件。(transitionEnd)。 为了实现这一点,你可以简单地做这样的事情:

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
投票

我也遇到了这个问题,只是通过将

decodeEntities
设置为 false 来解决它,你可以尝试这个解决方案。 这是我的代码

              <RenderHtml
                    contentWidth={screenSize.width}
                    source={{ html: pageData.html ?? '<p>no data</p>' }}
                    htmlParserOptions={{
                        decodeEntities: false,
                    }}
                    customHTMLElementModels={customHTMLElementModels}
                    renderers={renderers}
                    renderersProps={{
                        iframe: {
                            scalesPageToFit: true,
                            javaScriptEnabled: true,
                            domStorageEnabled: true,
                        },
                    }}
                    WebView={WebView}
                    defaultWebViewProps={{
                        scalesPageToFit: true,
                        javaScriptEnabled: true,
                        domStorageEnabled: true,
                    }}
                />
© www.soinside.com 2019 - 2024. All rights reserved.