webview_flutter: ^4.0.2 交互

1,014 阅读1分钟

微信截图_20230213192245.png

/*
首先保证App申明了网络权限
<uses-permission android:name="android.permission.INTERNET" />
设置sdk最低版本
minSdkVersion  19 
-----------------------------------------
Flutter 调用 JS
JS 调用 Flutter
 */
import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

const String html = '''
  <!DOCTYPE html>
<html lang="en">
<head>
    <meta name="viewport"
 content="width=device-width,initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0,user-scalable=no">
    <title>Title</title>
</head>
<body>
  <button onclick="callFlutter1()">js调用Flutter(javascriptChannels)</button>
  <button onclick="callFlutter2()">js调用Flutter(navigationDelegate)</button>
  <p id="p1" style="visibility:hidden;">
    Flutter 调用了 JS.
    Flutter 调用了 JS.
    Flutter 调用了 JS.
  </p>
<img alt="http图片报错" class="has" src="https://img-blog.csdnimg.cn/20190703173020692.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3hpYW9taV8w,size_16,color_FFFFFF,t_70" width="300" height="600">
</body>

<script>
var testCallBack = '测试返回字符串';
function callFlutter1(){
  channel.postMessage(JSON.stringify({name:"JS调用了Flutter"}));
}
function callFlutter2(){
    /*约定的url协议为:js://webview?arg1=111&arg2=222*/
    document.location = "https://www.baidu.com/";
}

function callJS(message){
  document.getElementById("p1").style.visibility = message;
}
</script>
</html>
  ''';

class _MyHomePageState extends State<MyHomePage> {
  WebViewController controller = WebViewController()
//JS执行模式 是否允许JS执行
    ..setJavaScriptMode(JavaScriptMode.unrestricted)
    ..setBackgroundColor(const Color(0xff003050))

    // ..loadRequest(Uri.parse('https://www.baidu.com'))
    ..loadHtmlString(html)
    //js调用Flutter
    ..addJavaScriptChannel('channel',
        onMessageReceived: (JavaScriptMessage message) {
      print('${message.message}----------${json.decode(message.message)}');
    });

  @override
  initState() {
    super.initState();
    controller.setNavigationDelegate(
      NavigationDelegate(
        onProgress: (int progress) {
          // Update loading bar.
          print('progress--------$progress');
        },
        onPageStarted: (String url) {
          print('Started--------$url');
        },
        onPageFinished: (String url) {
          print('Finished--------$url');
          // runJavaScript 没有then 返回
          //  controller.runJavaScript('callJS("visible")').then((value) {
          //   // print('$value'); // 报错
          // });
          // runJavaScriptReturningResult 有then 返回
          controller
              .runJavaScriptReturningResult('callJS("visible")')
              .then((value) => {print('+++++++$value')});
        },
        onWebResourceError: (WebResourceError error) {},
        // 地址监听
        onNavigationRequest: (NavigationRequest request) {
          if (request.url.startsWith('https://www.baidu.com/')) {
            print('blocking navigation to ------- ${request.url}');
            return NavigationDecision.prevent;
          }
          return NavigationDecision.navigate;
        },
      ),
    );
  }

  @override
  void didUpdateWidget(oldWidget) {
    super.didUpdateWidget(oldWidget);
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
  }

  @override
  void dispose() {
    super.dispose();
    controller
      ..clearLocalStorage()
      ..clearCache()
      ..removeJavaScriptChannel('channel');
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      backgroundColor: const Color(0xFF666666),
      body: Column(
        children: [
          Container(
              height: 400,
              width: double.infinity,
              color: Colors.greenAccent,
              alignment: Alignment.topCenter,
              child: WebViewWidget(controller: controller)),
        ],
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Text('Flutter调用JS'),
      ),
    );
  }

  void _incrementCounter() {
    controller.runJavaScriptReturningResult('testCallBack').then((value) => {
          print('+++++++$value') // 测试返回字符串
        });
  }
}