Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Error in Webview with targetSdkVersion 24

My app has a WebView which loads a simple HTML page with an iFrame that is used for loading an URL for payment process from a partner company (and I have no access to that url source).

When I point the targetSdkVersion to 19 everything works fine and I can make payments through the iFrame. However, when the targetSdkVersion is pointed to 24 I don't have the same luck.

In that case, the WebView manages to load the iFrame which is shown some EditText for entering with credit card information and a Button to submit it, but I always have an error 500 when I click on that button.

Since the payment URL is outsourced, I reached our partner company to get to know the origem from the 500 error. And they told me the error comes from a double call which makes me think something in the WebViewfrom api 24 is doing so.

The 500 error's print: enter image description here

The HTML file payment_html is the following:

<html>
    <head>
        <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
    </head>

    <body id="bodyContent" onload="addListener()" style="margin:0px;padding:0px;overflow:hidden;height:355px">
        <iframe id="ifrPagamento" src="partner_url"
            frameborder="0" style="overflow:hidden;width:100%;height:100%"></iframe>
    </body>

    <script type="text/javascript">

        function addListener() {
            window.addEventListener("message", receiveMessage, false);
        }

        function receiveMessage(message) {

            if (message) {

                var data = JSON.parse(message.data);

                if (data.code) {

                    if(data.code === "0") {
                        app.returnStatus(0);
                    }
                    else {
                        app.returnStatus(1);
                    }
                }

            }

        }

    </script>
</html>

The partner_url is replaced by the partner company's URL and I get it dynamically as bellow:

private void loadPage() {

    String url = (String) Session.getObject(Session.Key.PARTNER_URL, "");

    InputStream inputStream = mActivity.getResources().openRawResource(R.raw.payment_html);
    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

    try {

        int i = inputStream.read();

        while (i != -1) {

            byteArrayOutputStream.write(i);
            i = inputStream.read();

        }

        inputStream.close();

        String html = byteArrayOutputStream.toString();
        html = html.replace("partner_url", url);

        mWebView.loadDataWithBaseURL(null, html, "text/html", "UTF-8", null);

    } catch (IOException e) {

        Funcoes.printError(e.getMessage());

    }

}

I set the WebView up like the following:

private void setupWebView() {

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        WebView.setWebContentsDebuggingEnabled(true);
    }

    WebSettings webSettings = mWebView.getSettings();
    webSettings.setJavaScriptEnabled(true);
    webSettings.setSupportMultipleWindows(true);
    webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
    webSettings.setUseWideViewPort(true);
    webSettings.setLoadWithOverviewMode(true);
    webSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);
    webSettings.setAllowUniversalAccessFromFileURLs(true);
    webSettings.setCacheMode(WebSettings.LOAD_NO_CACHE);
    webSettings.setAppCacheEnabled(false);
    webSettings.setDomStorageEnabled(true);

    mWebView.setWebChromeClient(new WebChromeClient());
    mWebView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
    mWebView.addJavascriptInterface(new MyJavaScriptInterface(mActivity), "app");

    mWebView.setWebViewClient(new WebViewClient() {

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

        @Override
        public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
            view.loadUrl(request.getUrl().toString());
            return true;
        }

    });

}

And finally the layout.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingTop="10dp"
    android:paddingBottom="10dp"
    android:background="@color/white">

    <WebView
        android:id="@+id/webView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:scrollbars="none">

    </WebView>

    <ProgressBar
        android:id="@+id/progress"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:visibility="gone"/>

</RelativeLayout>

As I said before, I don't have the url's source because it's outsource. So I can't share it.

I've been struggling with this issue for a couple of weeks. Can anyone help me?

like image 621
Lennon Spirlandelli Avatar asked Jan 09 '17 21:01

Lennon Spirlandelli


People also ask

Why is my WebView not working?

You might often face issues in updating the chrome and Android System Webview. To fix this problem, you can reboot your device, check your internet connection, stop auto-updating all apps, clear Google Playstore cache, and storage, leave the beta testing program, and manually update Android WebView app from Playstore.

Do cookies work in WebView?

By default this is set to true and the WebView accepts cookies.

What is a WebView URL?

The WebView class is an extension of Android's View class that allows you to display web pages as a part of your activity layout. It does not include any features of a fully developed web browser, such as navigation controls or an address bar. All that WebView does, by default, is show a web page.

Is Android WebView deprecated?

This interface was deprecated in API level 12. This interface is now obsolete.


1 Answers

After a few weeks, I found out this https://developer.android.com/about/versions/android-5.0-changes.html#BehaviorWebView which explains the changes of api 21. Take a look at the WebView part that says:

If your application works with API level 21 or later:

  • The system locks mixed content and third-party cookies by default. To allow mixed content and third-party cookies, use the methods
    setMixedContentMode()and setAcceptThirdPartyCookies(), respectively.

So, I only added these configurations into WebViewand it worked perfectly.

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {

    webSettings.setMixedContentMode(MIXED_CONTENT_ALWAYS_ALLOW);
    CookieManager.getInstance().setAcceptThirdPartyCookies(mWebView, true);

}
like image 180
Lennon Spirlandelli Avatar answered Oct 06 '22 02:10

Lennon Spirlandelli