I have a Flutter project and I am using the webview_flutter package to create a Webview widget.
This is my main.dart file:
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:webview_flutter/webview_flutter.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Communication Bridge',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Native - JS Communication Bridge'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
WebViewController _controller;
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
@override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
appBar: AppBar(title: Text('Webview')),
body: WebView(
initialUrl: 'about:blank',
javascriptMode: JavascriptMode.unrestricted,
javascriptChannels: Set.from([
JavascriptChannel(
name: 'messageHandler',
onMessageReceived: (JavascriptMessage message) {
_scaffoldKey.currentState.showSnackBar(
SnackBar(
content: Text(
message.message)
)
);
})
]),
onWebViewCreated: (WebViewController webviewController) {
_controller = webviewController;
_loadHtmlFromAssets();
},
),
floatingActionButton: FloatingActionButton(
child: const Icon(Icons.arrow_upward),
onPressed: () {
_controller.evaluateJavascript('foo("message")');
},
),
);
}
_loadHtmlFromAssets() async {
String file = await rootBundle.loadString('assets/index.html');
_controller.loadUrl(Uri.dataFromString(
file,
mimeType: 'text/html',
encoding: Encoding.getByName('utf-8')).toString());
}
}
As you can see, I am loading a local html file into the webview (_loadHtmlFromAssets).
The html file has the following markup:
<html>
<head>
<title>My Local HTML File</title>
</head>
<body>
<script type="text/javascript">
function foo(msg) {
//Code
}
</script>
</body>
</html>
When the html contains the javascript like the code above, I have no problems and am able to communicate from the application to the webview.
I want to have the javascript code in a separate file, and not inside the html file.
<html>
<head>
<title>My Local HTML File</title>
</head>
<body>
<script src="script.js"></script> // <-------
</body>
</html>
When I tried doing this, I get the following error (where it's trying to reference methods defined in the javascript file):
I/chromium(15188): [INFO:CONSOLE(1)] "Uncaught ReferenceError: foo is not defined
I have added the file in my pubspec.yaml under assets, so that is not the issue.
I have seen this question on SO, but the solution there does not help.
You can copy paste run 4 full code main.dart, index.html, script.js, style.css below
And add android:usesCleartextTraffic="true" in AndroidManifest.xml
You can use package https://pub.dev/packages/webview_flutter_plus
webview_flutter_plus is a powerful extension of webview_flutter. This package helps to load Local HTML, CSS and Javascript content from Assets or Strings. This inherits all features of webview_flutter with minor API changes.
You can directly download full example code from https://github.com/shah-xad/webview_flutter_plus and test it
code snippet
WebViewPlus(
initialUrl: 'assets/index.html',
onWebViewCreated: (controller) {
this._controller = controller;
},
onPageFinished: (url) {
_controller.getHeight().then((double height) {
print("Height: " + height.toString());
setState(() {
_height = height;
});
});
},
javascriptMode: JavascriptMode.unrestricted,
),
setting of assets

working demo of example code

full code of main.dart
import 'package:flutter/material.dart';
import 'package:webview_flutter_plus/webview_flutter_plus.dart';
void main() {
runApp(WebViewPlusExample());
}
class WebViewPlusExample extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: WebViewPlusExampleMainPage(),
);
}
}
class WebViewPlusExampleMainPage extends StatefulWidget {
@override
_WebViewPlusExampleMainPageState createState() =>
_WebViewPlusExampleMainPageState();
}
class _WebViewPlusExampleMainPageState
extends State<WebViewPlusExampleMainPage> {
WebViewPlusController _controller;
double _height = 1000;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('webview_flutter_plus Example'),
),
body: ListView(
children: [
SizedBox(
height: 500,
child: WebViewPlus(
initialUrl: 'assets/index.html',
onWebViewCreated: (controller) {
this._controller = controller;
},
onPageFinished: (url) {
_controller.getHeight().then((double height) {
print("Height: " + height.toString());
setState(() {
_height = height;
});
});
},
javascriptMode: JavascriptMode.unrestricted,
),
)
],
),
);
}
}
full code of index.html
<!DOCTYPE HTML>
<html>
<head>
<title>webview_flutter_plus</title>
<link crossorigin="anonymous" href="style.css" rel="stylesheet">
</head>
<body>
<div id="testDiv">
webview_flutter_plus is an extension of webview_flutter to load HTML, CSS and Javascript even from Assets or String.
<br>
<br>
<br>
Please tap the text to see Javascript execution.
</div>
<script src="script.js"></script>
</body>
full code of script.js
var testDiv = document.getElementById("testDiv");
testDiv.addEventListener('click', function f(e) {
testDiv.setAttribute('style', 'background:red;')
console.log("style changed");
})
full code of style.css
#testDiv {
background: green;
color: white;
}
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