You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android 4.0-4.4设备使用Volley StringRequest遇SSLHandshakeException求助

解决Android 4.x设备上Volley StringRequest的SSL握手失败问题

这问题我之前碰过好多次了,你看到的SSLHandshakeException(具体是SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure),核心原因很明确:Android 4.0到4.4的系统默认不支持TLS 1.2及更高版本的加密协议,而现在几乎所有正规服务器都禁用了不安全的SSLv3、TLS 1.0这些旧协议,只认TLS 1.2+,所以4.x设备发起HTTPS请求时根本没法和服务器完成握手,直接报错。

具体解决方案

要让Volley在4.x设备上正常工作,我们需要自定义Volley的网络栈,强制开启TLS 1.2支持,分三步来:

  1. 写一个自定义的SSLSocketFactory,强制启用TLS协议
    这个类会让Socket优先使用TLS 1.2,同时兼容低版本的TLS协议,确保4.x系统能识别:
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;

public class TLSSocketFactory extends SSLSocketFactory {

    private SSLSocketFactory internalSSLSocketFactory;

    public TLSSocketFactory() throws KeyManagementException, NoSuchAlgorithmException {
        SSLContext context = SSLContext.getInstance("TLS");
        context.init(null, null, null);
        internalSSLSocketFactory = context.getSocketFactory();
    }

    @Override
    public String[] getDefaultCipherSuites() {
        return internalSSLSocketFactory.getDefaultCipherSuites();
    }

    @Override
    public String[] getSupportedCipherSuites() {
        return internalSSLSocketFactory.getSupportedCipherSuites();
    }

    @Override
    public Socket createSocket() throws IOException {
        return enableTLSOnSocket(internalSSLSocketFactory.createSocket());
    }

    @Override
    public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
        return enableTLSOnSocket(internalSSLSocketFactory.createSocket(s, host, port, autoClose));
    }

    @Override
    public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
        return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port));
    }

    @Override
    public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException {
        return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port, localHost, localPort));
    }

    @Override
    public Socket createSocket(InetAddress host, int port) throws IOException {
        return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port));
    }

    @Override
    public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
        return enableTLSOnSocket(internalSSLSocketFactory.createSocket(address, port, localAddress, localPort));
    }

    private Socket enableTLSOnSocket(Socket socket) {
        if(socket != null && (socket instanceof SSLSocket)) {
            ((SSLSocket)socket).setEnabledProtocols(new String[] {"TLSv1.2", "TLSv1.1", "TLSv1"});
        }
        return socket;
    }
}
  1. 自定义HurlStack,把上面的SSLSocketFactory集成进去
    这个类负责让Volley的网络请求使用我们自定义的Socket工厂:
import com.android.volley.toolbox.HurlStack;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSocketFactory;

public class TLSStack extends HurlStack {

    private SSLSocketFactory sslSocketFactory;

    public TLSStack(SSLSocketFactory sslSocketFactory) {
        this.sslSocketFactory = sslSocketFactory;
    }

    @Override
    protected HttpURLConnection createConnection(URL url) throws IOException {
        HttpURLConnection connection = super.createConnection(url);
        if (connection instanceof HttpsURLConnection) {
            ((HttpsURLConnection) connection).setSSLSocketFactory(sslSocketFactory);
        }
        return connection;
    }
}
  1. 初始化Volley RequestQueue时使用自定义栈
    在你创建RequestQueue的地方,替换掉默认的网络栈就行,记得加异常处理,防止初始化失败:
RequestQueue queue;
try {
    TLSSocketFactory tlsSocketFactory = new TLSSocketFactory();
    TLSStack tlsStack = new TLSStack(tlsSocketFactory);
    queue = Volley.newRequestQueue(getApplicationContext(), tlsStack);
} catch (KeyManagementException | NoSuchAlgorithmException e) {
    // 如果初始化失败, fallback到默认栈(虽然4.x可能还是不行,但至少不会崩溃)
    e.printStackTrace();
    queue = Volley.newRequestQueue(getApplicationContext());
}

// 接下来正常用你的StringRequest就行
StringRequest stringRequest = new StringRequest(Request.Method.GET, "你的HTTPS接口地址",
        response -> {
            // 处理成功响应的逻辑
        },
        error -> {
            // 处理错误的逻辑
        });
queue.add(stringRequest);

额外提醒

  • 如果你的服务器用的是自签名证书,那还得在TLSSocketFactory的context.init()方法里传入自定义的TrustManager,不然还是会证书验证失败。
  • 最好找个Android 4.x的真机或者模拟器测一测,确保生效。

内容的提问来源于stack exchange,提问作者Ashwin H

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 03:52:02