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');
}
}
更多关于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
来安装依赖。
基本用法
-
导入插件:
在你的 Dart 文件中导入
webview_flutter
和webview_flutter_android_pagecall
:import 'package:webview_flutter/webview_flutter.dart'; import 'package:webview_flutter_android_pagecall/webview_flutter_android_pagecall.dart';
-
创建 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)), ); }); } }
-
与 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); // 处理数据 } };
-
从 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)), ); }); }