Flutter WebView交互插件webview_flutter_android_pagecall的使用

webview_flutter_android_pagecall 是一个用于在 Flutter 中实现 WebView 的插件,它基于 webview_flutter 提供了更强大的功能。通过此插件,您可以轻松地在 Flutter 应用中嵌入 WebView,并实现与 JavaScript 的双向通信。

使用方法

1. 添加依赖

首先,在您的 pubspec.yaml 文件中添加以下依赖:

dependencies:
  webview_flutter_android_pagecall: ^版本号

然后运行 flutter pub get 来安装依赖。

2. 配置 WebView

为了使用 webview_flutter_android_pagecall,您需要配置 WebView 使用 SurfaceAndroidWebView 实现。以下是完整的示例代码。

示例代码

// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// ignore_for_file: public_member_api_docs

import 'dart:async';
import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:webview_flutter_android_pagecall/webview_surface_android.dart'; // 引入插件
import 'package:webview_flutter_platform_interface/webview_flutter_platform_interface.dart'; // 引入 WebView 接口
import 'package:permission_handler/permission_handler.dart'; // 用于请求权限

import 'web_view.dart'; // 自定义 WebView 组件

void main() {
  // 配置 WebView 使用 SurfaceAndroidWebView 实现
  WebView.platform = SurfaceAndroidWebView();

  runApp(MaterialApp(home: _WebViewExample()));
}

const String kNavigationExamplePage = '''
<!DOCTYPE html><html>
<head><title>Navigation Delegate Example</title></head>
<body>
<p>
The navigation delegate is set to block navigation to the youtube website.
</p>
<ul>
<ul><a href="https://www.youtube.com/">https://www.youtube.com/</a></ul>
<ul><a href="https://www.google.com/">https://www.google.com/</a></ul>
</ul>
</body>
</html>
''';

class _WebViewExample extends StatefulWidget {
  const _WebViewExample({Key? key}) : super(key: key);

  [@override](/user/override)
  _WebViewExampleState createState() => _WebViewExampleState();
}

class _WebViewExampleState extends State<_WebViewExample> {
  final Completer<WebViewController> _controller = Completer<WebViewController>();

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter WebView 示例'),
        // 添加导航按钮和菜单
        actions: <Widget>[
          _NavigationControls(_controller.future),
          _SampleMenu(_controller.future),
        ],
      ),
      body: Builder(builder: (context) {
        return WebView(
          initialUrl: 'https://app.pagecall.com/meet?room_id=64881244e31cc16e4e80cba4&logLevel=0', // 初始化 URL
          onWebViewCreated: (WebViewController controller) {
            _controller.complete(controller);
          },
          javascriptChannels: _createJavascriptChannels(context), // 添加 JavaScript 通道
          javascriptMode: JavascriptMode.unrestricted, // 允许执行 JavaScript
          debuggingEnabled: true, // 启用调试模式
        );
      }),
      floatingActionButton: favoriteButton(),
    );
  }

  // 创建 JavaScript 通道
  Set<JavascriptChannel> _createJavascriptChannels(BuildContext context) {
    return {
      JavascriptChannel(
        name: 'Snackbar',
        onMessageReceived: (JavascriptMessage message) {
          // 处理来自 JavaScript 的消息
          ScaffoldMessenger.of(context).showSnackBar(
            SnackBar(content: Text(message.message)),
          );
        },
      ),
    };
  }

  // 创建收藏按钮
  Widget favoriteButton() {
    return FutureBuilder<WebViewController>(
      future: _controller.future,
      builder: (BuildContext context, AsyncSnapshot<WebViewController> controller) {
        if (controller.hasData) {
          return FloatingActionButton(
            onPressed: () async {
              final String url = (await controller.data!.currentUrl())!;
              await Permission.microphone.request(); // 请求麦克风权限
              await Permission.audio.request(); // 请求音频权限
            },
            child: const Icon(Icons.favorite),
          );
        }
        return Container();
      },
    );
  }
}

// 导航控制按钮
class _NavigationControls extends StatelessWidget {
  const _NavigationControls(this._webViewControllerFuture)
      : assert(_webViewControllerFuture != null);

  final Future<WebViewController> _webViewControllerFuture;

  [@override](/user/override)
  Widget build(BuildContext context) {
    return FutureBuilder<WebViewController>(
      future: _webViewControllerFuture,
      builder: (BuildContext context, AsyncSnapshot<WebViewController> snapshot) {
        final bool webViewReady = snapshot.connectionState == ConnectionState.done;
        final WebViewController? controller = snapshot.data;

        return Row(
          children: <Widget>[
            IconButton(
              icon: const Icon(Icons.arrow_back_ios),
              onPressed: !webViewReady
                  ? null
                  : () async {
                      if (await controller!.canGoBack()) {
                        await controller.goBack();
                      } else {
                        return;
                      }
                    },
            ),
            IconButton(
              icon: const Icon(Icons.arrow_forward_ios),
              onPressed: !webViewReady
                  ? null
                  : () async {
                      if (await controller!.canGoForward()) {
                        await controller.goForward();
                      } else {
                        return;
                      }
                    },
            ),
            IconButton(
              icon: const Icon(Icons.replay),
              onPressed: !webViewReady
                  ? null
                  : () {
                      controller!.reload();
                    },
            ),
          ],
        );
      },
    );
  }
}

// 菜单选项
class _SampleMenu extends StatelessWidget {
  _SampleMenu(this.controller);

  final Future<WebViewController> controller;

  [@override](/user/override)
  Widget build(BuildContext context) {
    return FutureBuilder<WebViewController>(
      future: controller,
      builder: (BuildContext context, AsyncSnapshot<WebViewController> controller) {
        return PopupMenuButton<_MenuOptions>(
          onSelected: (_MenuOptions value) {
            switch (value) {
              case _MenuOptions.showUserAgent:
                _onShowUserAgent(controller.data!, context);
                break;
              case _MenuOptions.listCookies:
                _onListCookies(controller.data!, context);
                break;
              case _MenuOptions.clearCookies:
                _onClearCookies(controller.data!, context);
                break;
              case _MenuOptions.addToCache:
                _onAddToCache(controller.data!, context);
                break;
              case _MenuOptions.listCache:
                _onListCache(controller.data!, context);
                break;
              case _MenuOptions.clearCache:
                _onClearCache(controller.data!, context);
                break;
              case _MenuOptions.navigationDelegate:
                _onNavigationDelegateExample(controller.data!, context);
                break;
            }
          },
          itemBuilder: (BuildContext context) => <PopupMenuItem<_MenuOptions>>[
            PopupMenuItem<_MenuOptions>(
              value: _MenuOptions.showUserAgent,
              child: const Text('显示用户代理'),
              enabled: controller.hasData,
            ),
            const PopupMenuItem<_MenuOptions>(
              value: _MenuOptions.listCookies,
              child: Text('列出 Cookies'),
            ),
            const PopupMenuItem<_MenuOptions>(
              value: _MenuOptions.clearCookies,
              child: Text('清除 Cookies'),
            ),
            const PopupMenuItem<_MenuOptions>(
              value: _MenuOptions.addToCache,
              child: Text('添加到缓存'),
            ),
            const PopupMenuItem<_MenuOptions>(
              value: _MenuOptions.listCache,
              child: Text('列出缓存'),
            ),
            const PopupMenuItem<_MenuOptions>(
              value: _MenuOptions.clearCache,
              child: Text('清除缓存'),
            ),
            const PopupMenuItem<_MenuOptions>(
              value: _MenuOptions.navigationDelegate,
              child: Text('导航委托示例'),
            ),
          ],
        );
      },
    );
  }

  void _onShowUserAgent(WebViewController controller, BuildContext context) async {
    await controller.runJavascript(
        'Snackbar.postMessage("User Agent: " + navigator.userAgent);');
  }

  void _onListCookies(WebViewController controller, BuildContext context) async {
    final String cookies = await controller.runJavascriptReturningResult('document.cookie');
  }

  void _onAddToCache(WebViewController controller, BuildContext context) async {
    await controller.runJavascript(
        'caches.open("test_caches_entry"); localStorage["test_localStorage"] = "dummy_entry";');
  }

  void _onListCache(WebViewController controller, BuildContext context) async {
    await controller.runJavascript('caches.keys()'
        '.then((cacheKeys) => JSON.stringify({"cacheKeys" : cacheKeys, "localStorage" : localStorage}))'
        '.then((caches) => Snackbar.postMessage(caches))');
  }

  void _onClearCache(WebViewController controller, BuildContext context) async {
    await controller.clearCache();
  }

  void _onClearCookies(WebViewController controller, BuildContext context) async {
    final bool hadCookies = await WebView.platform.clearCookies();
    String message = '存在 Cookies。现在已删除!';
    if (!hadCookies) {
      message = '不存在 Cookies。';
    }
  }

  void _onNavigationDelegateExample(WebViewController controller, BuildContext context) async {
    final String contentBase64 = base64Encode(const Utf8Encoder().convert(kNavigationExamplePage));
    await controller.loadUrl('data:text/html;base64,$contentBase64');
  }
}
1 回复

更多关于Flutter WebView交互插件webview_flutter_android_pagecall的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


webview_flutter_android_pagecall 是一个用于在 Flutter 应用中实现与 Android WebView 交互的插件。它允许你在 Flutter 和 WebView 之间进行双向通信,从而实现更复杂的交互逻辑。

安装插件

首先,你需要在 pubspec.yaml 文件中添加 webview_flutter_android_pagecall 插件的依赖:

dependencies:
  flutter:
    sdk: flutter
  webview_flutter: ^4.0.0
  webview_flutter_android_pagecall: ^1.0.0

然后运行 flutter pub get 来安装依赖。

基本用法

  1. 导入插件

    在你的 Dart 文件中导入 webview_flutterwebview_flutter_android_pagecall

    import 'package:webview_flutter/webview_flutter.dart';
    import 'package:webview_flutter_android_pagecall/webview_flutter_android_pagecall.dart';
  2. 创建 WebView

    使用 WebView 组件来创建一个 WebView,并配置 WebViewController

    class MyWebView extends StatefulWidget {
      @override
      _MyWebViewState createState() => _MyWebViewState();
    }
    
    class _MyWebViewState extends State<MyWebView> {
      late WebViewController _controller;
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text('WebView Example'),
          ),
          body: WebView(
            initialUrl: 'https://example.com',
            javascriptMode: JavascriptMode.unrestricted,
            onWebViewCreated: (WebViewController webViewController) {
              _controller = webViewController;
              // 初始化 PageCall
              PageCall.init(_controller);
            },
            javascriptChannels: <JavascriptChannel>{
              _toasterJavascriptChannel(context),
            },
          ),
        );
      }
    
      JavascriptChannel _toasterJavascriptChannel(BuildContext context) {
        return JavascriptChannel(
            name: 'Toaster',
            onMessageReceived: (JavascriptMessage message) {
              // 处理来自 WebView 的消息
              ScaffoldMessenger.of(context).showSnackBar(
                SnackBar(content: Text(message.message)),
              );
            });
      }
    }
  3. 与 WebView 交互

    你可以使用 PageCall 来与 WebView 进行交互。例如,从 Flutter 向 WebView 发送消息:

    void sendMessageToWebView() async {
      await PageCall.callMethod('yourMethodName', {'key': 'value'});
    }

    在 WebView 中,你可以通过 JavaScript 来接收和处理这些消息:

    window.PageCall = {
      yourMethodName: function(data) {
        console.log('Received data from Flutter:', data);
        // 处理数据
      }
    };
  4. 从 WebView 向 Flutter 发送消息

    在 WebView 中,你可以通过 JavaScript 向 Flutter 发送消息:

    Toaster.postMessage('Hello from WebView!');

    在 Flutter 中,你可以通过 JavascriptChannel 来接收和处理这些消息:

    JavascriptChannel _toasterJavascriptChannel(BuildContext context) {
      return JavascriptChannel(
          name: 'Toaster',
          onMessageReceived: (JavascriptMessage message) {
            ScaffoldMessenger.of(context).showSnackBar(
              SnackBar(content: Text(message.message)),
            );
          });
    }
回到顶部
AI 助手
你好,我是IT营的 AI 助手
您可以尝试点击下方的快捷入口开启体验!