HttpURLConnection抛出java.net.SocketTimeoutException:在Android 4.1.1中SSL握手超时

HttpURLConnection抛出java.net.SocketTimeoutException:在Android 4.1.1中SSL握手超时,java,android,ssl,timeout,httpurlconnection,Java,Android,Ssl,Timeout,Httpurlconnection,我的代码在Android 5.0及更高版本中运行时运行良好。但在Android 4.1.1中,它抛出了java.net.SocketTimeoutException:SSL握手超时 URL url; HttpURLConnection connection = null; String charset = "UTF-8"; String accessToken = ""; try { ArrayList<NameValuePa

我的代码在Android 5.0及更高版本中运行时运行良好。但在Android 4.1.1中,它抛出了java.net.SocketTimeoutException:SSL握手超时

    URL url;
    HttpURLConnection connection = null; 
    String charset = "UTF-8";

    String accessToken = "";

    try {

        ArrayList<NameValuePair> postParameters = new ArrayList<NameValuePair>();
        postParameters.add(new BasicNameValuePair("client_id", CLIENT_ID));
        postParameters.add(new BasicNameValuePair("client_secret", CLIENT_SECRET));
        postParameters.add(new BasicNameValuePair("grant_type", CLIENT_CREDENTIALS_GRANT_TYPE));

        //Create connection
        url = new URL(ACCESS_TOKEN_URL);
        connection = (HttpURLConnection)url.openConnection();
        connection.setReadTimeout( 10000 /*milliseconds*/ );
        connection.setConnectTimeout( 15000 /* milliseconds */ );
        connection.setInstanceFollowRedirects(false);
        connection.setRequestMethod("POST");
        connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=" + charset);
        connection.setUseCaches(false);
        connection.setDoInput(true);
        connection.setDoOutput(true);

        //Send request
        DataOutputStream wr = new DataOutputStream(connection.getOutputStream());
        wr.write(getQuery(postParameters).getBytes(charset));
        wr.flush();
        wr.close();

        int responseCode = connection.getResponseCode();
        InputStream is = null;

        if(responseCode==HttpStatus.SC_OK) {
            is = connection.getInputStream();
        }
        else{
            is = connection.getErrorStream();
        }

        Log.d(TAG, "responseCode: "+responseCode);

        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
        StringBuilder sb = new StringBuilder();
        String line = null;

        while ((line = reader.readLine()) != null) {
            sb.append(line + "\n");
        }

        is.close();
        reader.close();

        String jsonResult = sb.toString();
        JSONObject jsonObject = new JSONObject(jsonResult);

        if(responseCode==HttpStatus.SC_OK){
            accessToken = jsonObject.getString("access_token");
            SettingsPreference.setAccessToken(accessToken);
            Log.d(TAG, "access token: "+accessToken);
        }
        else {
            accessToken = null;
        }

    } catch (Exception e) {
        e.printStackTrace();
    } finally {

        if(connection != null) {
          connection.disconnect(); 
        }
    }
URL;
HttpURLConnection=null;
字符串charset=“UTF-8”;
字符串accessToken=“”;
试一试{
ArrayList后参数=新的ArrayList();
添加(新的BasicNameValuePair(“客户端id”,客户端id));
添加(新的BasicNameValuePair(“client_secret”,client_secret));
添加(新的BasicNameValuePair(“授权类型”,客户端授权类型));
//创建连接
url=新url(访问令牌url);
connection=(HttpURLConnection)url.openConnection();
setReadTimeout(10000/*毫秒*/);
setConnectTimeout(15000/*毫秒*/);
connection.setInstanceFollowDirections(false);
connection.setRequestMethod(“POST”);
connection.setRequestProperty(“内容类型”,“应用程序/x-www-form-urlencoded;字符集=“+charset”);
connection.setUseCaches(false);
connection.setDoInput(true);
connection.setDoOutput(真);
//发送请求
DataOutputStream wr=新的DataOutputStream(connection.getOutputStream());
write(getQuery(postParameters).getBytes(charset));
wr.flush();
wr.close();
int responseCode=connection.getResponseCode();
InputStream=null;
if(responseCode==HttpStatus.SC_OK){
is=connection.getInputStream();
}
否则{
is=connection.getErrorStream();
}
Log.d(标签“responseCode:+responseCode”);
BufferedReader reader=新的BufferedReader(新的InputStreamReader(is));
StringBuilder sb=新的StringBuilder();
字符串行=null;
而((line=reader.readLine())!=null){
sb.追加(第+行“\n”);
}
is.close();
reader.close();
字符串jsonResult=sb.toString();
JSONObject JSONObject=新的JSONObject(jsonResult);
if(responseCode==HttpStatus.SC_OK){
accessToken=jsonObject.getString(“访问令牌”);
SettingsReference.setAccessToken(accessToken);
Log.d(标记“访问令牌:”+accessToken);
}
否则{
accessToken=null;
}
}捕获(例外e){
e、 printStackTrace();
}最后{
if(连接!=null){
连接断开();
}
}

我已经做了很多研究,这是相当令人沮丧的。我做错了什么?这是服务器问题吗?非常感谢您的帮助。

在较低的sdk级别上使用TrustManager?

您的旧设备上的受信任证书可能不是最新的。如果设备低于某个sdk级别,则可以尝试实现和使用

用于信任自签名或未正确签名的域的简单库。 但在您的情况下,我认为只为您的域创建一个例外,而不检查特定sdk级别下的证书是很方便的

此回购协议使用TrustManager对某些证书/域进行例外处理。如果您要使用它,请确保您正确使用它,因为Google Play可能不会接受您的应用程序更新/发布


请看我对其他问题的回答

我在4.1.1版本的URL连接上也有类似的问题,我的是EOF,而它在其他版本上工作得很好。我记得这篇文章帮助我意识到了问题所在。但是我认为soruce文件不再可用了。无论如何,帮助解决这个问题的是切换到DefaultHttp客户端,它可以在所有版本上工作…这是我向您推荐的最快的解决方案:尝试使用网络库/包装器,如DefaultHttp或Android客户端或OkHttp…您的手机4.1.1的时间正确吗?当客户端和服务器在时间上不同时,SSL不起作用。(当然还有约会!)看起来像是个bug,你可以试试看;我也有类似的问题,但是针对三星galaxy tab的,这是您的情况吗?@Paizo不仅在三星设备中,而且在Genymotion中也是如此。如果您提供URL以查看您尝试访问的主机是否有特殊之处,可能会有所帮助。可能与密码、协议版本、SNI、中间盒有关…添加一些说明here@Billa你是什么意思?我想你可以在另一篇文章的“我的答案”或SimpleTrust的github页面上找到你想要的任何东西。但是,如果你告诉我你需要什么样的描述,我会很乐意创建一个。(我没有在这里做详细描述,因为我不想重复上一个答案)证书问题不会导致握手超时。