在我的Android应用程序中,我需要在WebView
内显示第三方注册表单。不幸的是,我还需要支持Android版本< 4.3,连接到网站时出现SSL握手错误。但是,我能够使用自定义SSL上下文在Android 4.1+上创建直接请求,该上下文已明确启用TLS 1.1,但我无法将此SSL上下文传递到我的WebView
。我尝试制作自定义WebViewClient
private WebViewClient webViewClient = new WebViewClient() {
@Override
public void onPageFinished(WebView webView, String url) {
if (presenter != null) {
presenter.onLoadFinished();
}
}
@Override
public void onReceivedError(WebView webView,
WebResourceRequest request,
WebResourceError error) {
if (presenter != null) {
presenter.onLoadError();
}
}
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error){
handler.proceed();
}
@Override
public boolean shouldOverrideUrlLoading(WebView webView, String url) {
Request request = new Request.Builder().url(url).build();
final Handler handler = new Handler(mContext.getMainLooper());
//mOkHttpClient is an OkHttpClient with my custom SSLContext which has TLS 1.1 and TLS 1.2 enabled
mOkHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, final okhttp3.Response response) throws IOException {
handler.post(new Runnable() {
@Override
public void run() {
try {
webView.loadDataWithBaseURL(
null, response.body().string(), "text/html", "utf-8", null);
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
});
}
};
但由于shouldOverrideUrlLoading
未在POST请求中调用,因此无法正常工作。
有没有办法让这项工作(可能是WebView
的替代方案)?任何帮助表示赞赏。
答案 0 :(得分:4)
我不确定您是否可以使用当前的WebView,但是 我建议你看一下:https://crosswalk-project.org/documentation/android.html来替换WebView。
这是基于最新版本的Chrome和 你在用户运行的那个版本的Android上遇到了问题。
我确定还有其他选择,但这是我用于工作的那个,我知道工作。
祝你好运。
答案 1 :(得分:0)
某些版本不支持KitKat低于ssl和tsl的Android版本。
您可以通过黑客的方式来支持Kitkat以下的支持
1-)使用“ Retrofit或OkHttp”将页面加载为字符串,并将Webview加载为 字符串
implementation 'com.squareup.retrofit2:converter-scalars:2.1.0'
功能
public void getHtml(){
OkHttpClient client=new OkHttpClient();
try {
TLSSocketFactory tlsSocketFactory=new TLSSocketFactory();
if (tlsSocketFactory.getTrustManager()!=null) {
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.sslSocketFactory(tlsSocketFactory, tlsSocketFactory.getTrustManager());
client = builder
.build();
}
} catch (KeyManagementException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyStoreException e) {
e.printStackTrace();
}
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(columnist.getYaziAdress()+"/")
.client(client)
.addConverterFactory(ScalarsConverterFactory.create())
.build();
ApiEndPoint apiService =
retrofit.create(ApiEndPoint.class);
Call<ResponseBody> call = apiService.url(columnist.getYaziAdress());
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
try {
// yazarText.loadDataWithBaseURL(null,response.body().string(),"text/html", "utf-8", null);
String a = response.body().string();
yazarText.loadData(a, "text/html; charset=utf-8", "UTF-8");
yazarText.getSettings().setUserAgentString("Android");
yazarText.getSettings().setUseWideViewPort(true);
}catch (Exception e){
}
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Toast.makeText(ArticleActivity.this,getString(R.string.ttsNull),Toast.LENGTH_LONG).show();
}
});
}
TLSSocketFactory类
public class TLSSocketFactory extends SSLSocketFactory {
private SSLSocketFactory delegate;
private TrustManager[] trustManagers;
public TLSSocketFactory() throws KeyManagementException, NoSuchAlgorithmException, KeyStoreException {
generateTrustManagers();
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, trustManagers, null);
delegate = context.getSocketFactory();
}
private void generateTrustManagers() throws KeyStoreException, NoSuchAlgorithmException {
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init((KeyStore) null);
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
throw new IllegalStateException("Unexpected default trust managers:"
+ Arrays.toString(trustManagers));
}
this.trustManagers = trustManagers;
}
@Override
public String[] getDefaultCipherSuites() {
return delegate.getDefaultCipherSuites();
}
@Override
public String[] getSupportedCipherSuites() {
return delegate.getSupportedCipherSuites();
}
@Override
public Socket createSocket() throws IOException {
return enableTLSOnSocket(delegate.createSocket());
}
@Override
public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
return enableTLSOnSocket(delegate.createSocket(s, host, port, autoClose));
}
@Override
public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
return enableTLSOnSocket(delegate.createSocket(host, port));
}
@Override
public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException {
return enableTLSOnSocket(delegate.createSocket(host, port, localHost, localPort));
}
@Override
public Socket createSocket(InetAddress host, int port) throws IOException {
return enableTLSOnSocket(delegate.createSocket(host, port));
}
@Override
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
return enableTLSOnSocket(delegate.createSocket(address, port, localAddress, localPort));
}
private Socket enableTLSOnSocket(Socket socket) {
if(socket != null && (socket instanceof SSLSocket)) {
((SSLSocket)socket).setEnabledProtocols(new String[] {"TLSv1.1", "TLSv1.2"});
}
return socket;
}
@Nullable
public X509TrustManager getTrustManager() {
return (X509TrustManager) trustManagers[0];
}
}
Api终点
@GET()
Call<ResponseBody> url(@Url String url);
2-)使用Php脚本将html作为字符串返回到您的应用程序