targetSdkVersion 24 的 Webview 出错
Error in Webview with targetSdkVersion 24
我的应用程序有一个 WebView
,它加载一个简单的 HTML 页面和一个 iFrame,用于从合作伙伴公司加载 URL 付款流程(我没有访问 url 来源)。
当我将 targetSdkVersion
指向 19 时,一切正常,我可以通过 iFrame 付款。但是,当 targetSdkVersion
指向 24 时,我就没有同样的运气了。
在那种情况下,WebView
设法加载了显示一些 EditText
用于输入信用卡信息和 Button
用于提交的 iFrame,但我总是有单击该按钮时出现错误 500。
由于付款URL是外包的,所以我联系了我们的合作伙伴公司,以了解500错误的来源。他们告诉我错误来自两次调用,这让我觉得 WebView
from 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 的来源,因为它是外包的。所以我不能分享它。
几周来我一直在为这个问题苦苦挣扎。谁能帮帮我?
几个星期后,我发现这个 https://developer.android.com/about/versions/android-5.0-changes.html#BehaviorWebView 解释了 api 21 的变化。看看 WebView
的部分说:
如果您的应用程序使用 API 级别 21 或更高版本:
- 系统默认锁定混合内容和 third-party cookie。到
允许混合内容和 third-party cookie,使用方法
分别为 setMixedContentMode() 和 setAcceptThirdPartyCookies()。
所以,我只将这些配置添加到 WebView
中,并且效果很好。
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
webSettings.setMixedContentMode(MIXED_CONTENT_ALWAYS_ALLOW);
CookieManager.getInstance().setAcceptThirdPartyCookies(mWebView, true);
}
我的应用程序有一个 WebView
,它加载一个简单的 HTML 页面和一个 iFrame,用于从合作伙伴公司加载 URL 付款流程(我没有访问 url 来源)。
当我将 targetSdkVersion
指向 19 时,一切正常,我可以通过 iFrame 付款。但是,当 targetSdkVersion
指向 24 时,我就没有同样的运气了。
在那种情况下,WebView
设法加载了显示一些 EditText
用于输入信用卡信息和 Button
用于提交的 iFrame,但我总是有单击该按钮时出现错误 500。
由于付款URL是外包的,所以我联系了我们的合作伙伴公司,以了解500错误的来源。他们告诉我错误来自两次调用,这让我觉得 WebView
from 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 的来源,因为它是外包的。所以我不能分享它。
几周来我一直在为这个问题苦苦挣扎。谁能帮帮我?
几个星期后,我发现这个 https://developer.android.com/about/versions/android-5.0-changes.html#BehaviorWebView 解释了 api 21 的变化。看看 WebView
的部分说:
如果您的应用程序使用 API 级别 21 或更高版本:
- 系统默认锁定混合内容和 third-party cookie。到
允许混合内容和 third-party cookie,使用方法
分别为 setMixedContentMode() 和 setAcceptThirdPartyCookies()。
所以,我只将这些配置添加到 WebView
中,并且效果很好。
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
webSettings.setMixedContentMode(MIXED_CONTENT_ALWAYS_ALLOW);
CookieManager.getInstance().setAcceptThirdPartyCookies(mWebView, true);
}