Android - 如何在API级别4上拦截Android WebViewClient中的表单POST?

33

我有一个附加在WebView上的WebViewClient

webView.setWebViewClient(new MyWebViewClient());

这是我实现的MyWebViewClient

private class MyWebViewClient extends WebViewClient {

    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
      webView.loadUrl(url);
      return true;
    }    
}

我通过 loadUrl()WebView 提供一个要加载的 URL。如果页面中有一个链接 (a href...),我的 shouldOverrideUrlLoading 方法将被调用并且我可以拦截链接的点击。

然而,如果我有一个方法为 POST 的表单,则不会调用 shouldOverrideUrlLoading 方法。

我注意到类似的问题在这里:http://code.google.com/p/android/issues/detail?id=9122 ,其中建议在我的 WebView 中重写 postUrl 方法。但是,此 API 仅从 API level 5 开始提供。

如果我使用的是 API level 4,我该怎么办?是否有其他拦截表单提交的方法?


你可以尝试在WebViewClient中重写onPageStarted回调函数。 - bhups
谢谢。我尝试了一下,它能正常工作,但问题在于我不想加载表单页面 - 它是一个虚假的URL,所以最终会得到webview错误页面。为此,我通过检查onPageStarted中URL是否与我的表单URL匹配来解决这个问题,如果是,则在我的应用程序中处理并告诉webViewClient返回。这听起来合理吗? - manisha
你找到解决方案了吗? - Sohaib
现在,我们有WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request)可以拦截POST请求。但它仍然不完美;你不能简单地设置自定义头并让请求继续——你必须全部自己处理 - Alex Cohn
3个回答

5

你真的需要使用POST请求吗?如果你想在本地处理表单数据,为什么不让一段JavaScript代码处理你的表单,并使用addJavascriptInterface与“本地”Java代码进行交互。例如:

WebView engine = (WebView) findViewById(R.id.web_engine);       
engine.getSettings().setJavaScriptEnabled(true); 
engine.addJavascriptInterface(new MyBridge(this), "bridge");
engine.loadUrl(...)

您的桥接器基本上可以是任何类,并且您应该能够直接从JavaScript访问其方法。例如:
public class MyBridge {

    public MyBridge(Context context) {
         // ...
    }

    public String doIt(String a, String b) {
            JSONArray result = new JSONArray();
            result.put("Hello " + a);
            result.put("Hello " + b);
            return result.toString();       
    }

您的HTML / JavaScript可能如下所示:

<script type="text/javascript">
    $("#button").click(function() {
        var a = $("#a").val();
        var b = $("#b").val();

        var result=JSON.parse(bridge.doIt(a, b));
        // ...
    }
</script>

<input id="a"><input id="b"><button id="button">click</button>

那是理想的解决方案,但不幸的是在2.3仿真器和那一代各种手机上似乎无法使用。请查找以下错误的VM崩溃:JNI WARNING: jarray 0x40533560 points to non-array object (Ljava/lang/String;),Google搜索了解更多信息。 - EtienneSky

5

这是一个已知的问题,即 shouldOverrideUrlLoading 没有捕获POST请求。详细信息请参见http://code.google.com/p/android/issues/detail?id=9122

使用GET方法!个人尝试使用POST,因为我预期 GET 参数会有一些限制(如 URL 长度),但我成功地通过本地 GET 传递了32000字节而没有出现任何问题。


7
我需要找到这个问题的解决方案。因为在我的情况下,实际上我无法切换到GET。我不明白为什么在Android中会忽略它。原因是什么? - boburShox
覆盖webView中的postUrl。自API级别5以来可用。 - Mike Keskinov
2
我尝试了,但没有成功。无法处理。 - boburShox
7
我也需要解决这个问题。我需要在我的WebView中添加自定义标题,以便对所有发出的请求进行处理。我首先加载一个重定向到另一页的url(通过POST方式),但我无法捕获该重定向并正确地添加自定义标题。我无法控制服务器使用POST而不是GET的事实。 - ssawchenko

-3

我认为你可以重写WebViewClient中的onLoadResource(WebView view, String url)函数。该函数已在API LEVEL 1中添加。

WebView将加载指定URL的资源时,将调用此函数。资源包括嵌入式URL的jscssiframe。代码示例如下:

    @Override
    public void onLoadResource(WebView view, String url) {
        if (url.indexOf("http://www.example.com") != -1 && view != null) {
            // open url in default browser
            view.stopLoading();
            view.getContext().startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
        }
    }

问题要求截取POST请求而不是尝试加载资源。两者是不同的。 - Gem
对于那些给这个回答点“减号”的人:根据HTTP标准,“资源”不仅仅是文件(如js,css等)。“资源”可以是URI指向的任何东西。例如,API端点也是资源。 - forallepsilon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接