3

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,%
1
  • There is an evaluateJavascript function for webViewController. It won't run your js file but it allows you to run javascript inside webview. You can check it, maybe it will be useful for you Commented Jan 27, 2020 at 9:03

1 Answer 1

3

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"
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.