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 WebView
from api 24 is doing so.
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?
2 Answers
Answers 1
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 WebView
and it worked perfectly.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { webSettings.setMixedContentMode(MIXED_CONTENT_ALWAYS_ALLOW); CookieManager.getInstance().setAcceptThirdPartyCookies(mWebView, true); }
Answers 2
For applications targeted to API level JELLY_BEAN_MR1 and above, only public methods that are annotated with JavascriptInterface can be accessed from JavaScript. For applications targeted to API level JELLY_BEAN or below, all public methods (including the inherited ones) can be accessed...
// Code
@RequiresApi(api = Build.VERSION_CODES.M) @Override public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) { super.onReceivedError(view, request, error); Log.d(TAG, error.getErrorCode() + ": " + error.getDescription()); }
@Override public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { super.onReceivedError(view, errorCode, description, failingUrl); Log.d(TAG, failingUrl + "\t" + errorCode + ": " + description); } @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) @Override public void onReceivedHttpError(WebView view, WebResourceRequest request, WebResourceResponse errorResponse) { super.onReceivedHttpError(view, request, errorResponse); Log.d(TAG, String.valueOf(errorResponse.getStatusCode())); }
0 comments:
Post a Comment