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

Flutter InAppWebView Android与iOS编码URL不一致问题求助

Flutter InAppWebView跨平台URL编码差异解决方法

我们在Flutter应用中使用InAppWebView组件时,发现shouldOverrideUrlLoading方法返回的编码URL在iOS和Android平台存在不一致,导致解码后Android端的JSON格式异常。

平台差异详情

编码后URL(encodedURL)

  • iOS:%22coordinates%22:%22%7B%5C%22y1%5C%22:193.0,%5C%22x1%5C%22:491.0,%5C%22y2%5C%22:162.0,%5C%22x2%5C%22:522.0%7D%22
  • Android:%22coordinates%22:%22%7B/%22y1/%22:521.0,/%22x1/%22:753.0,/%22y2/%22:490.0,/%22x2/%22:784.0%7D%22

解码后URL(decodedURL)

  • iOS:"coordinates" : "{"y1":521.0,"x1":753.0,"y2":490.0,"x2":784.0}"
  • Android:"coordinates": "{/"y1/":521.0,/"x1/":753.0,/"y2/":490.0,/"x2/":784.0}"

可见iOS使用%5C转义双引号,而Android使用/,导致Android端解码后的JSON无法正常解析。

现有实现代码

InAppWebView组件代码

InAppWebView(
          key: webViewKey,
          initialUrlRequest: URLRequest(url: Uri.parse(widget.url)),
          initialOptions: inAppWebViewGroupOptions(),
          onWebViewCreated: (InAppWebViewController webViewController) async {
            _appWebViewController = webViewController;
            if (widget.onWebViewCreated != null) {
              widget.onWebViewCreated!(_appWebViewController!);
            }
          },
          onLoadStart: (InAppWebViewController controller, Uri? url) async {
            if (widget.onProgressChanged != null) {
              widget.onPageStarted!(url.toString());
            }
          },
          onLoadStop: (InAppWebViewController controller, Uri? url) async {
            if (widget.onPageFinished != null) {
              widget.onPageFinished!(url.toString());
            }
          },
          onProgressChanged: (InAppWebViewController controller, int progress) {
            if (widget.onProgressChanged != null) {
              widget.onProgressChanged!(progress);
            }
          },
          shouldOverrideUrlLoading: (controller, navigationAction) async {
            var request = navigationAction.request;
            var url = request.url;
            bool absolute = url!.hasAbsolutePath;

            if (absolute) {
              setCookies(url.toString());
            }

            if (widget.shouldOverrideUrlLoading != null) {
              widget.shouldOverrideUrlLoading!(controller, navigationAction);
            }
            // always allow all the other requests
            return NavigationActionPolicy.ALLOW;
          },
          androidOnPermissionRequest: (controller, origin, resources) async {
            return PermissionRequestResponse(
                resources: resources,
                action: PermissionRequestResponseAction.GRANT);
          },
          onLoadError: (_, __, int code, String message) {
            if (widget.onPageError != null) {
              widget.onPageError!(code, message);
            }
            _webViewCubit?.showLinearProgressIndicator(false, 1);
          },
        );

URL解码代码

String jsonString = Uri.decodeFull(data[1]);

解决方法

方案1:解码后统一处理Android端转义字符

通过平台判断,将Android端解码后的/"替换为标准双引号,消除格式差异:

import 'dart:io';

// 解码后处理逻辑
String rawDecoded = Uri.decodeFull(data[1]);
String jsonString;

if (Platform.isAndroid) {
  // 替换Android端的特殊转义符
  jsonString = rawDecoded.replaceAll(r'/"', '"');
} else {
  jsonString = rawDecoded;
}

方案2:预处理Android平台的URL编码

在shouldOverrideUrlLoading中对Android端的URL进行预处理,将/替换为标准转义符%5C后再处理:

shouldOverrideUrlLoading: (controller, navigationAction) async {
  var request = navigationAction.request;
  var url = request.url;
  bool absolute = url!.hasAbsolutePath;

  if (absolute) {
    String urlStr = url.toString();
    // 针对Android平台替换转义符编码
    if (Platform.isAndroid) {
      urlStr = urlStr.replaceAll('/%22', '%5C%22');
    }
    setCookies(urlStr);
  }

  if (widget.shouldOverrideUrlLoading != null) {
    widget.shouldOverrideUrlLoading!(controller, navigationAction);
  }
  return NavigationActionPolicy.ALLOW;
},

方案3:配置Android WebView的编码规则

修改InAppWebView的Android平台配置,强制使用标准URL编码逻辑:

InAppWebViewGroupOptions inAppWebViewGroupOptions() {
  return InAppWebViewGroupOptions(
    android: AndroidInAppWebViewOptions(
      useHybridComposition: true,
      domStorageEnabled: true,
      defaultTextEncodingName: "utf-8",
      // 启用WebView的标准URL编码行为
      allowContentAccess: true,
    ),
    ios: IOSInAppWebViewOptions(),
  );
}

方案4:从Web端统一输出格式

如果可以控制Web页面代码,修改Web端的URL跳转逻辑,统一使用%5C转义双引号,从源头保证跨平台输出一致。


内容的提问来源于stack exchange,提问作者A User

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 21:01:44