Ошибка в Webview с помощью targetSdkVersion 24

Мое приложение имеет WebView который загружает простую HTML-страницу с iFrame, которая используется для загрузки URL-адреса для процесса оплаты от компании-партнера (и у меня нет доступа к этому источнику URL-адреса).

Когда я указываю targetSdkVersion на 19, все работает нормально, и я могу делать платежи через iFrame. Однако, когда targetSdkVersion указывает на 24, я не имею такой же удачи.

В этом случае WebView управляет загрузкой iFrame, на которой показан некоторый EditText для ввода информации о кредитной карте и Button для ее отправки, но у меня всегда есть ошибка 500, когда я нажимаю на эту кнопку.

Поскольку URL-адрес платежа передается на аутсорсинг, я добрался до нашей партнерской компании, чтобы узнать исходник из 500 ошибок. И они сказали мне, что ошибка исходит из двойного вызова, который заставляет меня думать, что что-то в WebView от api 24 делает.

Печать 500 ошибок: Введите описание изображения здесь

HTML файл payment_html выглядит следующим образом:

 <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> 

partner_url заменяется URL-адресом партнерской компании, и я получаю его динамически:

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

Я установил WebView следующим образом:

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

И, наконец, 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> 

Как я уже говорил, у меня нет источника url, потому что это аутсорсинг. Поэтому я не могу поделиться им.

Я боролся с этой проблемой в течение пары недель. Может кто-нибудь мне помочь?

Solutions Collecting From Web of "Ошибка в Webview с помощью targetSdkVersion 24"

Через несколько недель я узнал об этом https://developer.android.com/about/versions/android-5.0-changes.html#BehaviorWebView, который объясняет изменения api 21. Посмотрите на часть WebView которой говорится:

Если ваше приложение работает с API уровня 21 или более поздней версии:

  • По умолчанию система блокирует смешанный контент и сторонние файлы cookie. Чтобы разрешить смешанный контент и сторонние файлы cookie, используйте методы
    SetMixedContentMode () и setAcceptThirdPartyCookies (), соответственно.

Итак, я только добавил эти конфигурации в WebView и он отлично работал.

 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { webSettings.setMixedContentMode(MIXED_CONTENT_ALWAYS_ALLOW); CookieManager.getInstance().setAcceptThirdPartyCookies(mWebView, true); } 

Для приложений, ориентированных на уровень API JELLY_BEAN_MR1 и выше, доступ к JavaScript можно получить только из общедоступных методов, которые аннотируются с помощью JavascriptInterface. Для приложений, ориентированных на уровень API JELLY_BEAN или ниже, доступны все общедоступные методы (включая унаследованные) …

// Код

@RequiresApi (api = Build.VERSION_CODES.M) @Override public void onReceivedError (представление WebView, запрос WebResourceRequest, ошибка WebResourceError) {super.onReceivedError (просмотр, запрос, ошибка); 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())); }