Wonil Suh
Wonil Suh

Reputation: 1121

react native webview load from device local file system

I'm trying to load .html, .js, .css files from device's local file system into React Native WebView component. I was able to get the path to the index.html file but specifying this as the url for the WebView simply throws an error. How would I go about this? Please help!

Upvotes: 22

Views: 32940

Answers (5)

apgsn
apgsn

Reputation: 751

I stumbled upon the same issue and, after running in circles for hours trying all sorts of solutions, I finally solved it by following this tutorial. Major kudos to the author.

In the article there's some extra info which is a bit outdated, so here's the concise version instead:

  • create a folder in your main project root (e.g. /html);
  • put all of your files in a folder (e.g. Web, with index.html being your WebView entrypoint), give it a .bundle extension (e.g. Web.bundle), and place it into /html;

Now you have to add these files to the project so they are recognized and bundled together in your next build, this process is done differently in iOS and Android:

  • iOS: open your project in Xcode, drag n drop Web.bundle into the project's main folder, and confirm the dialog with the "Copy items if needed" option left unchecked;
  • Android: open /android/app/build.gradle and add:
android {
  ...
  sourceSets { 
    main { assets.srcDirs = ['src/main/assets', '../../html'] } 
  }
}

Now rebuild your project from scratch to have your changes take effect.

In your WebView file, calculate the path to index.html and feed it to the WebView:

const sourceUri = (Platform.OS === 'android' ? 'file:///android_asset/' : '')
    + 'Web.bundle/index.html';

return (
  <WebView
    source={{ uri: sourceUri }}
    originWhitelist={['*']}
    javaScriptEnabled={true}
    allowFileAccess={true}
  />
);

This will load your index.html and all of its js and css files, as long as they're included in the bundle.

Upvotes: 7

Rias
Rias

Reputation: 1996

In react native it is now possible to require an HTML file and use it as the source for the web view like this (the path is relative to the react-native file you use it in):

const webapp = require('./webapp/index.html');

and the use it in the WebView like this:

<WebView source={webapp} />

Unfortunately this does not load CSS and JavaScript files, that are referenced in the HTML. A solution could be, to write all the CSS and JS inline (e.g. by using a build process).

Upvotes: 16

dryymoon
dryymoon

Reputation: 131

Place this script in any file of ReactNative or your code, recomended to first or top index file. And it will fix problem, tested on RN0.39

import { Platform } from 'react-native';
import { setCustomSourceTransformer } from 'react-native/Libraries/Image/resolveAssetSource';

setCustomSourceTransformer(function (resolver) {

  if (Platform.OS === 'android'
    && !resolver.serverUrl
    && !resolver.bundlePath
    && resolver.asset.type === 'html') {
    resolver.bundlePath = '/android_asset/';
  }

  return resolver.defaultAsset();
});

Upvotes: 0

Doppio
Doppio

Reputation: 2188

I was able to include html5/javascript into project by using { html: , baseUrl: } as source. But to be frank, it's more like a lucky shot.

<WebView source={{ html: HTML, baseUrl: 'web/' }} />

I have index.html, which require pano2vr_player.js and pano.xml to make this code work.

const HTML = `
<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
		<meta http-equiv="X-UA-Compatible" content="IE=edge" />
		<title></title>
		<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0" />
		<meta name="apple-mobile-web-app-capable" content="yes" />
		<meta name="apple-mobile-web-app-status-bar-style" content="black" />
		<meta name="mobile-web-app-capable" content="yes" />
		<style type="text/css" title="Default">
			body, div, h1, h2, h3, span, p {
				font-family: Verdana,Arial,Helvetica,sans-serif;
			}
    </style>
	</head>
	<body>
		<script type="text/javascript" src="pano2vr_player.js">
		</script>
		<div id="container" style="width:100%;height:100%;">
		<br>Loading...<br><br>
		This content requires HTML5 with CSS3 3D Transforms or WebGL.
    </div>
		<script type="text/javascript">
			// create the panorama player with the container
			pano=new pano2vrPlayer("container");
		  window.addEventListener("load", function() {
			  pano.readConfigUrlAsync("pano.xml");
		  });
		</script>
	</body>
</html>`;

class PanoView extends Component {

  render() {
    return (
      <View>
        <WebView
          style={{ flex: 1, width: 1024, height: 768 }}
          source={{ html: HTML, baseUrl: 'web/' }}
          javaScriptEnabledAndroid={true} />
      </View>
    );
  }
}

And finally add files/folder ('/web' same as baseUrl) to XCode project

enter image description here

And it works! But I'm not sure how...

Upvotes: 9

stan229
stan229

Reputation: 2607

You may have to wrap your own Native Module to do this. React Native's WebView uses UIWebView, for info on loading a local file take a look here: https://gist.github.com/amster/9160860

However it is recommended you use WKWebView, you can wrap one yourself relatively easily. There is currently a repo that is WIP: https://github.com/qrush/react-native-wkwebview

Accomplishing loading local resources using WKWebView can be found in this answer: https://stackoverflow.com/a/28676439/398136

Upvotes: 3

Related Questions