You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android中webview_flutter POST请求自定义Header的实现问题求助

解决Android下webview_flutter POST请求带Header后页面无样式、JS报错的问题

问题根源分析

  • 资源加载路径错误:用loadHtmlString加载纯HTML时,页面内的相对路径资源(CSS、JS、图片)默认以about:blank为基准URL,无法正确请求服务器上的资源,导致页面无样式。
  • jQuery注入时机错误:原代码在loadHtmlString前执行注入,此时页面DOM尚未初始化,注入的脚本无法生效,且页面原有依赖jQuery的代码已提前执行,抛出未定义错误。
  • 链接跳转无请求:页面base URL为about:blank,点击相对链接时请求的URL无效,因此服务器无日志。

可行解决方案

方案一:给loadHtmlString设置baseUrl(最直接有效)

通过指定baseUrl,让页面内的相对路径资源以服务器域名为基准加载,同时调整jQuery注入时机到页面加载完成后。

修改代码如下:

  1. 初始化WebViewController时添加页面加载完成监听:
@override
void initState() {
  super.initState();
  controller = WebViewController()
    ..setJavaScriptMode(JavaScriptMode.unrestricted)
    ..setNavigationDelegate(
      NavigationDelegate(
        // 页面加载完成后注入jQuery
        onPageFinished: (String url) async {
          await injectJQuery();
        },
      ),
    );
  _loadRequestWithAuthHeader();
  controller.addJavaScriptChannel(
    'Flutter',
    onMessageReceived: (JavaScriptMessage message) {
      print('JavaScript Error: ${message.message}');
    },
  );
}
  1. 修改_loadRequestWithAuthHeader中的loadHtmlString调用,添加baseUrl参数:
if (response.statusCode == 200) {
  // 传入服务器域名作为baseUrl,解决相对资源加载问题
  await controller.loadHtmlString(
    response.body,
    baseUrl: Config.domain,
  );
}
  1. 保留原injectJQuery方法即可,此时注入时机正确,脚本会生效。

方案二:针对Android平台使用原生WebView的POST带Header能力

借助webview_flutter_android插件的扩展能力,直接调用原生WebView的postUrl方法,绕过WebViewController.loadRequest的限制:

  1. 添加依赖到pubspec.yaml:
dependencies:
  webview_flutter: ^4.0.0
  webview_flutter_android: ^3.0.0
  1. 修改请求逻辑,针对Android平台使用原生实现:
import 'package:webview_flutter_android/webview_flutter_android.dart';
import 'dart:convert';
import 'dart:typed_data';

Future<void> _loadRequestWithAuthHeader() async {
  const storage = FlutterSecureStorage();
  final token = await storage.read(key: 'token');
  if (token != null) {
    final url = Uri.parse('${Config.domain}/mobile_index.php');
    final headers = {
      'Authorization': 'Bearer $token',
      'Content-Type': 'application/json',
    };

    // 针对Android平台使用原生postUrl方法
    if (controller.platform is AndroidWebViewController) {
      await (controller.platform as AndroidWebViewController).postUrl(
        url: url.toString(),
        postData: Uint8List.fromList(utf8.encode('')), // POST请求体,按需修改
        headers: headers,
      );
    } else {
      // iOS平台可直接用loadRequest
      await controller.loadRequest(
        url,
        method: LoadRequestMethod.post,
        headers: headers,
      );
    }
  }
}

方案三:改用Cookie传递认证信息(需服务器配合)

手动发起POST请求后,将服务器返回的Set-Cookie保存,再让WebView加载页面时自动携带Cookie:

final response = await http.post(url, headers: headers);
if (response.statusCode == 200) {
  // 提取Set-Cookie头
  final cookie = response.headers['set-cookie'];
  if (cookie != null) {
    // 将Cookie注入WebView
    await controller.runJavaScript('document.cookie = "$cookie";');
  }
  // 直接加载页面,WebView会自动携带Cookie
  await controller.loadRequest(Uri.parse('${Config.domain}/mobile_index.php'));
}

说明

  • 方案一完全遵循官方替代方案的思路,无需修改服务器逻辑,适配性强。
  • 方案二直接利用原生Android能力,避免loadHtmlString带来的资源加载问题,但需针对平台做适配。
  • 方案三需服务器支持Cookie认证,适合原本就用Cookie做会话管理的场景。

内容的提问来源于stack exchange,提问作者Nate Perdomo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 20:25:56