添加 HTML 资源路径到 pubspec.yaml;更新 Auth 页面以使用新的 Webview 组件加载本地 HTML 文件;重构 WebviewPage 以支持加载本地资产和注入 JavaScript 通信桥接;清理不必要的导入和注释。
This commit is contained in:
@@ -5,16 +5,19 @@ import 'package:webview_flutter_android/webview_flutter_android.dart';
|
||||
import 'package:webview_flutter_wkwebview/webview_flutter_wkwebview.dart';
|
||||
|
||||
class WebviewPage extends StatefulWidget {
|
||||
final String url;
|
||||
final String? url;
|
||||
final String? title;
|
||||
final String? assetPath;
|
||||
|
||||
const WebviewPage({super.key, required this.url, this.title});
|
||||
const WebviewPage({super.key, this.url, this.title, this.assetPath});
|
||||
|
||||
@override
|
||||
State<WebviewPage> createState() => WebviewPageState();
|
||||
}
|
||||
|
||||
class WebviewPageState extends State<WebviewPage> {
|
||||
static const String _javaScriptChannelName = 'AppBridge';
|
||||
|
||||
WebViewController? _controller;
|
||||
bool _isLoading = true;
|
||||
String? _errorMessage;
|
||||
@@ -26,11 +29,12 @@ class WebviewPageState extends State<WebviewPage> {
|
||||
}
|
||||
|
||||
Future<void> _initController() async {
|
||||
if (widget.url?.isEmpty ?? true) {
|
||||
if ((widget.url?.isEmpty ?? true) && widget.assetPath == null) {
|
||||
return;
|
||||
}
|
||||
final params = _createPlatformParams();
|
||||
final controller = WebViewController.fromPlatformCreationParams(params)
|
||||
late final WebViewController controller;
|
||||
controller = WebViewController.fromPlatformCreationParams(params)
|
||||
..setJavaScriptMode(JavaScriptMode.unrestricted)
|
||||
..setBackgroundColor(Colors.transparent)
|
||||
..setNavigationDelegate(
|
||||
@@ -46,8 +50,9 @@ class WebviewPageState extends State<WebviewPage> {
|
||||
_errorMessage = null;
|
||||
});
|
||||
},
|
||||
onPageFinished: (String url) {
|
||||
onPageFinished: (String url) async {
|
||||
debugPrint('webview - page finished: $url');
|
||||
await _injectPostMessageBridge(controller);
|
||||
if (!mounted) return;
|
||||
setState(() => _isLoading = false);
|
||||
},
|
||||
@@ -72,17 +77,28 @@ class WebviewPageState extends State<WebviewPage> {
|
||||
),
|
||||
);
|
||||
|
||||
controller.addJavaScriptChannel(
|
||||
_javaScriptChannelName,
|
||||
onMessageReceived: (JavaScriptMessage message) {
|
||||
_onMessageReceived(message);
|
||||
},
|
||||
);
|
||||
|
||||
if (controller.platform is AndroidWebViewController) {
|
||||
AndroidWebViewController.enableDebugging(kDebugMode);
|
||||
await (controller.platform as AndroidWebViewController)
|
||||
.setMediaPlaybackRequiresUserGesture(false);
|
||||
}
|
||||
|
||||
final targetUrl = widget.url ?? '';
|
||||
try {
|
||||
await controller.loadRequest(Uri.parse(targetUrl));
|
||||
if (widget.assetPath != null) {
|
||||
await controller.loadFlutterAsset(widget.assetPath!);
|
||||
} else {
|
||||
final targetUrl = widget.url ?? '';
|
||||
await controller.loadRequest(Uri.parse(targetUrl));
|
||||
}
|
||||
} catch (e) {
|
||||
debugPrint('webview - loadRequest failed: $e');
|
||||
debugPrint('webview - load failed: $e');
|
||||
if (!mounted) return;
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
@@ -95,6 +111,81 @@ class WebviewPageState extends State<WebviewPage> {
|
||||
setState(() => _controller = controller);
|
||||
}
|
||||
|
||||
void _onMessageReceived(JavaScriptMessage message) {
|
||||
debugPrint('收到来自 WebView 的消息: ${message.message}');
|
||||
}
|
||||
|
||||
/// 脚本注入传输给h5 数据
|
||||
Future<void> _injectH5NeedData(WebViewController controller) async {
|
||||
try {
|
||||
await controller.runJavaScript('''
|
||||
(function () {
|
||||
if (window.__appBridgePostMessageBridgeInstalled) {
|
||||
return;
|
||||
}
|
||||
|
||||
window.__appBridgePostMessageBridgeInstalled = true;
|
||||
window.addEventListener('message', function (event) {
|
||||
if (!window.AppBridge || !window.AppBridge.postMessage) {
|
||||
return;
|
||||
}
|
||||
|
||||
var payload = event.data;
|
||||
if (typeof payload !== 'string') {
|
||||
try {
|
||||
payload = JSON.stringify(payload);
|
||||
if (typeof payload === 'undefined') {
|
||||
payload = String(event.data);
|
||||
}
|
||||
} catch (error) {
|
||||
payload = String(payload);
|
||||
}
|
||||
}
|
||||
|
||||
window.AppBridge.postMessage(payload);
|
||||
});
|
||||
})();
|
||||
''');
|
||||
} catch (e) {
|
||||
debugPrint('webview - inject postMessage bridge failed: $e');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _injectPostMessageBridge(WebViewController controller) async {
|
||||
// try {
|
||||
// await controller.runJavaScript('''
|
||||
// (function () {
|
||||
// if (window.__appBridgePostMessageBridgeInstalled) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
// window.__appBridgePostMessageBridgeInstalled = true;
|
||||
// window.addEventListener('message', function (event) {
|
||||
// if (!window.AppBridge || !window.AppBridge.postMessage) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
// var payload = event.data;
|
||||
// if (typeof payload !== 'string') {
|
||||
// try {
|
||||
// payload = JSON.stringify(payload);
|
||||
// if (typeof payload === 'undefined') {
|
||||
// payload = String(event.data);
|
||||
// }
|
||||
// } catch (error) {
|
||||
// payload = String(payload);
|
||||
// }
|
||||
// }
|
||||
|
||||
// window.AppBridge.postMessage(payload);
|
||||
// });
|
||||
// })();
|
||||
// ''');
|
||||
// } catch (e) {
|
||||
// debugPrint('webview - inject postMessage bridge failed: $e');
|
||||
// }
|
||||
}
|
||||
|
||||
PlatformWebViewControllerCreationParams _createPlatformParams() {
|
||||
if (WebViewPlatform.instance is WebKitWebViewPlatform) {
|
||||
return WebKitWebViewControllerCreationParams(
|
||||
@@ -110,27 +201,8 @@ class WebviewPageState extends State<WebviewPage> {
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.transparent,
|
||||
extendBodyBehindAppBar: true,
|
||||
appBar: AppBar(
|
||||
backgroundColor: Colors.transparent,
|
||||
elevation: 0,
|
||||
title: Text(
|
||||
widget.title ?? '',
|
||||
style: const TextStyle(color: Colors.white),
|
||||
),
|
||||
leading: IconButton(
|
||||
icon: const Icon(Icons.arrow_back, color: Colors.white),
|
||||
onPressed: () async {
|
||||
final controller = _controller;
|
||||
if (controller != null && await controller.canGoBack()) {
|
||||
await controller.goBack();
|
||||
} else {
|
||||
if (context.mounted) Navigator.of(context).maybePop();
|
||||
}
|
||||
},
|
||||
),
|
||||
iconTheme: const IconThemeData(color: Colors.white),
|
||||
),
|
||||
|
||||
// appBar: myAppBar(context: context),
|
||||
body: _buildBody(),
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user