33

I have a WebViewClient attached to my WebView like so:

webView.setWebViewClient(new MyWebViewClient());

Here is my implementation of MyWebViewClient:

private class MyWebViewClient extends WebViewClient {

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

I give the WebView a URL to load via loadUrl(). If I have a link (a href...) in the page, my shouldOverrideUrlLoading method is called and I can intercept the link click.

However, if I have a form whose method is POST, the shouldOverrideUrlLoading method is not called.

I noticed a similar issue here: http://code.google.com/p/android/issues/detail?id=9122 which seems to suggest overriding postUrl in my WebView. However, this API is only available starting from API level 5.

What can I do if I'm on API level 4? Is there any other way to intercept form posts?

jbihan
  • 3,053
  • 2
  • 24
  • 34
manisha
  • 4,454
  • 2
  • 18
  • 10
  • You can try overriding onPageStarted callback in the WebViewClient. – bhups Sep 08 '10 at 03:27
  • Thanks. I tried that and it works alright, but the problem is that I don't want the form's page to load - it's a fake URL so I end up getting the webview error page. I worked around this by checking in onPageStarted if the URL matches my form URL, and if so, handle this in my app and then tell the webViewClient to go back. Does that sound reasonable? – manisha Sep 09 '10 at 17:07
  • These days, we have `WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request)` which does intercept POST. It's still less than perfect; you cannot simply set a custom header and let the request proceed – you must [handle it all yourslef](https://stackoverflow.com/a/66357697/192373) – Alex Cohn Apr 13 '21 at 19:57

3 Answers3

5

This is known issue, that shouldOverrideUrlLoading don't catch POST. See http://code.google.com/p/android/issues/detail?id=9122 for details.

Use GET! I personally tried using POST, because I expected some limitation of GET parameters (i.e. length of URL), but I just successfully passed 32000 bytes through GET locally without any problems.

Mike Keskinov
  • 11,614
  • 6
  • 59
  • 87
  • 7
    I really need to find the solution to this. Because, in my case, it is not in my hands to switch to GET, actually. I cannot understand how it is missed in android. What was the reason. – boburShox Mar 13 '13 at 11:57
  • Override `postUrl` in `webView`. This is available since API level 5. – Mike Keskinov Mar 13 '13 at 17:23
  • 2
    I did, no success. Not handling. – boburShox Mar 14 '13 at 03:51
  • 7
    I am also in need of a solution for this. I need to add a custom header to all requests going out through my WebView. I first load in a url that redirects (via POST wheee!) to another page, and I am unable to catch that redirect and correctly add the custom header. I have no control over the server and the fact that it is using a POST instead of a GET. – ssawchenko Aug 20 '14 at 23:46
5

Do you really need to use a POST? If you want to handle formdata locally, why not have a piece of javascript handle your form and interface with "native" java code using addJavascriptInterface. E.g.

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

Your bridge can be any class basically and you should be able to access its methods directly from javascript. E.g.

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();       
    }

Your html / javascript could look like:

<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>
Ivo van der Wijk
  • 16,341
  • 4
  • 43
  • 57
  • That is the ideal solution but unfortunately does not seem to work on the 2.3 emulator and various phones of that generation. Look for VM crashes with the following error: JNI WARNING: jarray 0x40533560 points to non-array object (Ljava/lang/String;) Google for that for more information – EtienneSky Jan 30 '12 at 07:05
-3

I think you can override onLoadResource(WebView view, String url) from WebViewClient. This function is Added in API LEVEL 1.

This function is called when WebView will load the resource specified by the given url. Resource include js, css, iframe embeded url. Code example like this:

    @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)));
        }
    }
jbihan
  • 3,053
  • 2
  • 24
  • 34
wangzhengyi
  • 856
  • 8
  • 8
  • In the question it is asked to intercept POST request not attempting resource loading. Both are different. – Gem Oct 23 '15 at 06:39
  • For those who adds minuses to this response: according to HTTP standard, "resource" is not only file (js, css and so on). "Resource" is anything URI points to. E.g., API endpoints are resources too. – forallepsilon Aug 31 '17 at 13:53