ReactNative - Webview没有在Android

时间:2017-02-28 19:21:51

标签: android webview react-native

我无法在ReactNative上获取Webview以在物理Android设备上执行注入的JavaScript。在过去的两天里,我尽可能地搜索网络,但仍未找到解决方案。测试结果如下:

  1. iOS模拟器 - 一切顺利
  2. iPhone - 一切顺利
  3. Android模拟器 - 一切顺利
  4. 物理设备,Sony Xperia Z2,Sony Xperia Z5 Compact和LG G4 - NOTHING
  5. 我的Webview定义如下:

    <WebView
      style={styles.webView}
      source={{
        html: html,
        baseUrl: 'web/'
      }}
      injectedJavaScript={'render(' + JSON.stringify(this.state.data) + ');'}
      javaScriptEnabledAndroid={true}
      scrollEnabled={false}
      bounces={false}
      renderLoading={() => <LoadingIndicator />}
    />
    

    我也尝试过指定javaScriptEnabled,但无济于事。我还尝试使用较小的脚本来对页面上的元素进行着色或使用window.postMessage将消息发回给应用程序,但没有任何反应。我需要将数据注入HTML,这将根据提供的数据为我呈现图形。我最后的办法是手动构建HTML,并附加数据作为提供给Webview的标记的一部分,但我真的很想保持简单,只需按照工作方式< /强>

    我使用的是最新版本的ReactNative(0.41),手机正在运行Android 6 +。

3 个答案:

答案 0 :(得分:6)

我刚刚发现Android WebView似乎将任何JS注入单行,即使它包含换行符。这意味着丢失的分号肯定会导致问题,或者在我的情况下,由//分隔的注释。使用/**/进行评论后,我的注入JavaScript再次运行。

答案 1 :(得分:4)

好吧,在将这个问题暂时搁置一段时间并找到(不那么优雅)问题的解决方案之后,我决定分享我最终做的事情:

  1. 我声明HTML将沿着这些行以常量字符串传递给WebView:const html = '<html>...<script>...[INJECTEDSCRIPT]</script></html>';
  2. 我在React组件生命周期的componentDidMount()事件中检索了数据,并使用this.setState({ data: retrievedData });
  3. 为其设置了状态变量
  4. 当然,这迫使组件重新呈现自己,之后我现在可以获得数据&#34;传递&#34;到WebView
  5. 看到我无法找到任何优雅或可用的方式使用injectedJavaScript属性以我想要的方式工作(如问题中所述),我求助于替换{{1带有序列化数据的HTML常量中的值。
  6. 我知道,这不是最优雅的解决方案,但它是唯一一个可以在多种设备和仿真器配置中可靠工作的解决方案。示例,为简洁起见编辑,如下:

    [INJECTEDSCRIPT]

答案 2 :(得分:0)

我一直在努力使Javascript(预嵌入和注入)也能执行。到目前为止,一个简单而更好的解决方案是使用WebViewBridge。之后,一切都按预期进行。这里是软件包的链接:cnpmjs.org/package/react-native-webview-bridge。

这里有一个演示:

import React, {
    Component
} from 'react';

 import PropTypes from 'prop-types';

 import {
     Platform,
     WebView,
     ActivityIndicator,
} from 'react-native'; 

import WevViewBridge from 'react-native-webview-bridge';

// TODO: Keep in mind that you should ALWAYS edit
//       two separate file and keep them matched.
const IOS_WEB_PAGE_SOURCE = './webPage/wordBody.html';
const ANDROID_WEB_PAGE_SOURCE = 'file:///android_asset/webPage/wordBody.html';

export default class WordBody extends Component {

    static propTypes = {
        data: PropTypes.object.isRequired,
    }

    _injectedScript = `
        (function(){
            let data = ${JSON.stringify(this.props.data)};
            refresh(data);
        })();
    `;

    render() {
        /*
         * We are using Platform.select here for two reasons:
         * 0. Everythig work fine for IOS using `WebView` from RN
         * 1. Android doesn't load web ressource with `require`
         * 2. On Android, `WebView` from react-native doesn't
         *    execute JavaScript so we use `WebViewBridge`. 
         */
        return Platform.select({
            ios: (<WebView
                    style = {{backgroundColor: 'rgba(0, 0, 0, 0)', flex:1,}}
                    scalesPageToFit
                    source = {require(IOS_WEB_PAGE_SOURCE)}
                    javaScriptEnabled={true}
                    originWhitelist={['*']}
                    injectedJavaScript = {this._injectedScript}
                    renderLoading={() => <ActivityIndicator/>}
                />),
            android: (<WevViewBridge
                        style = {{backgroundColor: 'rgba(0, 0, 0, 0)', flex:1,}}
                        scalesPageToFit
                        source = {{uri:ANDROID_WEB_PAGE_SOURCE}}
                        javaScriptEnabled={true}
                        // originWhitelist={['*']}
                        injectedJavaScript = {this._injectedScript}
                        renderLoading={() => <ActivityIndicator/>}
                    />)
        });
    };
}