本机反应 - webview在构建发布apk时不呈现本地html

时间:2017-12-05 20:15:55

标签: android react-native webview build apk

我已经在webview中为我的应用程序渲染了本地html,它在iOS和Android上都很棒。它是嵌入了svg标签的html。

但是一旦我在Android上生成了apk并尝试在我的手机上本地运行,它就不会渲染。

即使在导出.ipa文件时,也能在iOS上正常运行

const VECTOR_BODY_HTML = require('../custom_views/vector-body.html');
...
         <WebView
           ref={component => this.mWebView = component}

           automaticallyAdjustContentInsets = {false}
           contentInset={{top:0 , left:0 ,bottom:-20, right:0}}

           source = {VECTOR_BODY_HTML}
           scalesPageToFit = {false}

           onLoad = {() => {
               this.updateBodyViewBox(bodyWidth, bodyHeight);
               this.initColorMap();
               this.populateBodyMap(15)
             }
             }
           onMessage = {(data) => {this.onMessage(data);}}

           style = {{height:bodyHeight}}
          >
          </WebView>

3 个答案:

答案 0 :(得分:3)

好的,这是一个复杂的问题。基本上,require()在调试模式下可以与iOS和Android一起使用,但是一旦你构建一个Android apk for release,一切都会走下坡路。因此,我将这一点分解为后人的阶段,毫无疑问,是未来的我。

要进行设置,请假设您的文件名为your.html,并且该文件名位于src/assets/your.html文件夹中。

步骤1)您需要在考虑跨平台支持的情况下更新<WebView />组件:

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

<WebView
  source={Platform.OS === 'ios' ? 
    require('../src/assets/your.html') :
    {uri: 'file:///android_asset/your.html'}
  }
  domStorageEnabled
  javaScriptEnabled
/>

所以,这里发生的事情是你需要告诉android允许访问dom存储你需要启用javascript(除非你不这样做&#39) ;很好)。显然,默认情况下,iOS在iOS上启用,默认情况下在Android上禁用。

这里做的是,如果平台是iOS,我们只需要正常的文件,一切都适用于dev / prod。但是,对于android我们需要告诉它从android的默认android存储位置加载文件file:///android_asset/。此文件直接与位于android/app/src/main/assets/的文件夹对应,您可以将your.html复制到该文件夹​​。所以它看起来像android/app/src/main/assets/your.html

此时一切都会正常工作 - 但是,您可能会发现直接复制文件令人难以置信令人讨厌。至少,我做到了。

因此,对于第2步,您可以升级应用build.gradle文件以自动更新资产。因此,请继续打开位于android/app/build.gradle的app build.gradle文件。在底部的某个地方(其他task命令所在的位置)继续并放置:

task copyReactNativeHTML(type: Copy) {
  from '../../src/assets/'
  into 'src/main/assets'
}

gradle.projectsEvaluated {
  bundleDebugJsAndAssets.dependsOn(copyReactNativeHTML)
  bundleReleaseJsAndAssets.dependsOn(copyReactNativeHTML)
}

现在您应该能够将文件自动复制到正确的资源文件夹中,以便您可以通过android_asset从javascript访问它们。

那就是它!有点,它应该适用于大多数用例,但有一些关于android的奇怪的事情和使用ProGuard缩小你的构建。基本上,如果你想使用它,你需要确保your.html不加标记。

因此对于(可选)步骤3)打开位于android/app/proguard-rules.pro的proguard设置文件并添加以下内容:

-keepclassmembers class fqcn.of.javascript.interface.for.webview {
  public *;
}

就是这样,应该为您设置所有内容以使用WebViews跨平台。我不能真正赞美这篇文章,因为我刚刚从https://github.com/facebook/react-native/issues/16133拼凑了一堆人民解决方案。特别是,Arshiamidos和scottschmitz解决方案最具启发性。我建议大家都给他们买啤酒:)。

答案 1 :(得分:0)

 <WebView
  style={{
          flex: 1,
          marginLeft: Platform.OS === 'ios' ? 25 : 0,
          marginRight: Platform.OS === 'ios' ? 25 : 0,
          width: deviceWidth - 0,
          borderRadius: 4
          }}
          originWhitelist={['*']}
        source={Platform.OS === 'ios' ?
                require('../../../components/Heartrate.html') :
                {uri: 'file:///android_asset/Heartrate.html'}
                 }
         bounces={false}
         javaScriptEnabled={true}
         directionalLockEnabled={true}
         vertical={false}
         ref={(webView) => this.heartRateWebView = webView}
    />

在android 中将HTML放入Android->资产文件夹

和iOS将HTML放入文件夹中的React Native Project中

enter image description here

答案 2 :(得分:0)

我正在使用 webview 在我的本机应用程序中显示一个图表。它在开发过程中加载图表,但不在发布 apk 中显示。

我的网页视图代码如下。

<View
        style={{ flex: 1, backgroundColor: 'yellow', alignSelf: 'stretch' }}>
        <WebView
          ref={(r) => (this.webRef = r)}
          originWhitelist={['*']}
          source={{ html: this.html() }}
          style={{ width: 380, height: 300, backgroundColor: 'lightblue' }}
          domStorageEnabled={true}
          javaScriptEnabled={true}
          injectedJavaScriptBeforeContentLoaded={this.pipeConsoleLog()}
          onMessage={this.handleMessage.bind(this)}
        />
      </View>

而 html() 就像...

  html() {
            return `
            <html lang="en">
            
            <head>
            <title>seating chart</title>
            <meta name="viewport" content="width=device-width, initial-scale=1.0" />
            <script src="https://cdn-na.seatsio.net/chart.js"></script>
            </head>
            <body>
            <script>
            let promises = [];
            let promiseCounter = 0;
            
            const resolvePromise = (promiseId, data) => {
                promises[promiseId](data)
            }
                </script>
                <div id="chart"></div>
                <script>
                let chart = new seatsio.SeatingChart(${this.configAsString()}).render();
                </script>
                
            </body>
            </html>
            `;
        }

但是图表没有加载。我试图将以下代码放入 Proguard 文件中,但应用程序崩溃了。

-keepclassmembers class fqcn.of.javascript.interface.for.webview {
  public *;
}