Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jellybean/ICS Android HTTP Post Method + WebView.RestoreState

I'm using the API 17 emulator to test a page containing a web view.

  1. The webview first loads a page using the GET method.
  2. Then the user submits the web form using HTTP POST method which causes a second page to load.
  3. At this point if I rotate the screen I receive the "Webpage not available" error seen below. This only occurs if the page was loaded using the POST method. Note: I'm trying to restore the webview's state using webview.restoreState (see code below). Is there any way to tell Android to re-post the form data and reload the page instead of displaying this error message?!

I can't reproduce this same issue on KitKat, Lollipop, or Gingerbread... I can only reproduce this issue on Jellybean and Ice Cream Sandwich so far...

I've also confirmed this is an issue on an actual Nexus 7 device running Jellybean, so it's not an emulator-only problem.

Note: I'm not particularly interesting in using something like android:configChanges="orientation|keyboardHidden". As I understand it, this might solve my rotation issues, but the problem may still resurface if the activity state needs to be restored for other reasons.


Screenshots:

Step #1: Load the WebView Normally

Step 1

Step #2: Submit the Form (uses HTTP Post Method)

Step 2

Step #3: Rotate the screen to trigger webview.restoreState - error occurs

Step 3


Code:

Here is some sample code to go along with my question. The code is in Mono C# but should be very nearly identical to Java.

public class MainActivity : Activity
{
    WebView webview;

    protected override void OnCreate(Bundle bundle)
    {
        base.OnCreate(bundle);

        webview = new WebView(this);
        SetContentView(webview);

        if (bundle == null)
            webview.LoadUrl("http://2-dot-npwc-services.appspot.com/test-post.jsp");
        else
            webview.RestoreState(bundle);
    }

    protected override void OnSaveInstanceState(Bundle bundle)
    {
        base.OnSaveInstanceState(bundle);
        webview.SaveState(bundle);
    }
}

The sample HTML page that is performing the POST method looks like this:

<html>
<form action="test-post.jsp" method="post">
<input type="text" name="test" value="test"/>
<input type="submit"/>
</form>

<p>You entered: <%=request.getParameter("test")%></p>
</html>
like image 326
craigrs84 Avatar asked Apr 07 '15 03:04

craigrs84


1 Answers

The browser it's doing good (although it's a pain for us), you have 2 ways:

1- Keeping the webView instance and restoring the state, adding like you said android:configChanges="orientation|keyboardHidden"

2- Or reloading the post petition again.

I take the first one and if i get some error, i will go back to the last page. Doing static content, so on rotation no network or a new petition it's needed on each rotation, which if not, on server side will be a pain too.

To achieve the "if error go back" you need to set a Custom WebClient and override this method

webview.setWebViewClient(new WebViewClient() {
    @Override
    public void onReceivedError(WebView webView, int errorCode, String description, String failingUrl) {
        if ( webView.canGoBack() ) {
           Toast.makeText(MainActivity.this, R.string.error_web, Toast.LENGTH_SHORT).show();
           webView.goBack();
        }
    }
});

You can filter by errorCode to go back when you want, in some kind of error you can go back on other do other thing. I dont' know which error raises this POST request or if you want more filter on other situations, so i'm sure you can do a fine grain filter using it.

Edit: You have here the possible error codes WebViewClient Error Codes

I hope this helps.

like image 158
Sulfkain Avatar answered Oct 21 '22 21:10

Sulfkain