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
相关产品推荐
相关产品推荐

