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

Posted

技术标签:

【中文标题】反应原生 - 构建发布 apk 时 webview 不呈现本地 html【英文标题】:react native - webview does not render local html when building release apk 【发布时间】:2018-05-19 14:31:47 【问题描述】:

我在 webview 中为我的应用程序渲染了本地 html,它在 iosandroid 上都运行良好。这是一个嵌入了 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>

【问题讨论】:

【参考方案1】:

好的,这是一个复杂的问题。基本上,require() 在调试模式下可以在 iOS 和 Android 上正常工作,但是一旦你构建了一个用于发布的 Android apk,一切都会走下坡路。因此,我将把它分解为后代,毫无疑问,未来的我。

对于设置,我们假设您的文件名为 your.html,并且它位于您的 src/assets/your.html 文件夹中。

所以第 1 步)您需要更新 &lt;WebView /&gt; 组件并考虑跨平台支持:

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(除非您不这样做,否则没关系)。显然,javascript 在 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 的应用程序 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 的解决方案最具启发性。我建议我们都去给他们买啤酒:)。

【讨论】:

我在我的 react-native android 应用程序中尝试渲染 chart.js 时遇到了同样的问题。图表在应用程序处于调试模式时呈现。一旦我生成发布 APK,图表就不会呈现。按照你上面的步骤,仍然没有帮助。有任何想法吗? @Boomer Rogers 你能告诉我们更多关于你尝试了什么以及你的代码是什么样子的信息吗?【参考方案2】:
 <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 项目中

【讨论】:

以上是关于反应原生 - 构建发布 apk 时 webview 不呈现本地 html的主要内容,如果未能解决你的问题,请参考以下文章

Webview顶部的按钮反应原生

反应原生发布模式是不是必须托管api / db?

反应原生 html postMessage 无法到达 WebView

反应原生:上传 apk 后,Play 商店有权限问题(CAMERA,RECORD_AUDIO,...)

隐藏反应原生 webview 底部状态栏

反应原生生成签名的APK