How can I use a js file associated with an html in Flutter. I use the webview_flutter plug-in to load the index.html file and it works, but I am not able to load the js file This is my Flutter code:
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: WebView(
initialUrl: '',
javascriptMode: JavascriptMode.unrestricted,
onWebViewCreated: (WebViewController webViewController) {
_webViewController = webViewController;
_loadHtmlFromAssets();
},
),
_loadHtmlFromAssets() async {
String fileHtmlContents = await rootBundle.loadString('files/index.html');
_webViewController.loadUrl(Uri.dataFromString(fileHtmlContents, mimeType: 'text/html', encoding: Encoding.getByName('utf-8')).toString());
}
And this is my html file
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script type="text/javascript" **src="files/plotter.js**"></script>
<title>Test plotter</title>
</head>
<body>
<!-- <script type="text/javascript" src="plotter.js"></script> -->
<div id='test'></div>
<script type="text/javascript">
This is the message that appears in conosle
I/chromium(31201): [INFO:CONSOLE(86)] "Uncaught ReferenceError: Plotter is not defined", source: data:text/html;charset=utf-8,%
Instead of reading the asset and then loading from data uri, just pass the asset path like this:
_loadHtmlFromAssets() async {
_webViewController.loadUrl('file:///android_asset/flutter_assets/files/index.html');
}
And in index.html file, the script path should be relative. For me index.html and index.js were in same path so this works:
<script src="index.js"></script>
And my pubspec.yml looks like this:
assets:
- files/index.html
- files/index.js
Edit
Platform independent solution using local_assets_server:
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:local_assets_server/local_assets_server.dart';
import 'package:webview_flutter/webview_flutter.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) => MaterialApp(home: MyWidget());
}
class MyWidget extends StatefulWidget {
@override
_MyWidgetState createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
String address;
int port;
bool isListening = false;
@override
initState() {
_initServer();
super.initState();
}
_initServer() async {
final server = new LocalAssetsServer(
address: InternetAddress.loopbackIPv4,
assetsBasePath: 'files',
);
final address = await server.serve();
setState(() {
this.address = address.address;
port = server.boundPort;
isListening = true;
});
}
List<String> propList = [];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('My WebView'),
),
body: !isListening ? Center(child: CircularProgressIndicator()) : WebView(
initialUrl: 'http://$address:$port',
javascriptMode: JavascriptMode.unrestricted,
onWebViewCreated: (WebViewController webViewController) {
}),
);
}
}
And for android, add usesCleartextTraffic="true" in manifest file:
<application
....
android:usesCleartextTraffic="true"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With