Нужно решить проблему с эксепшн.
HTTP FAILED: javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted:
ssl=0xb80e0c40: Failure in SSL library, usually a protocol error
Api 19 андроид 4.4
Сам код
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
ConnectionSpec spec = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
.allEnabledCipherSuites()
.build();
OkHttpClient client = new OkHttpClient.Builder()
.connectionSpecs(Collections.singletonList(spec))
.addInterceptor(interceptor)
.build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.unsplash.com/")
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.build();
unsplash = retrofit.create(Unsplash.class);
unsplash.getPic(howMany, key).enqueue(new Callback<GiveMePhoto>() {
@Override
public void onResponse(Call<GiveMePhoto> call, Response<GiveMePhoto> response) {
Log.e("log", "onResponse: body " );
}
@Override
public void onFailure(Call<GiveMePhoto> call, Throwable t) {
Log.e("log", "onFailure: ");
}
});
Вот логи
D/OkHttp: --> GET https://api.unsplash.com/photos/random?count=1&client_id=семь35a6f98aa0896a1ab0b0cdc65d5a8132477661e18a2236a238e08f526f7323e
D/OkHttp: --> END GET
D/OkHttp: <-- HTTP FAILED: javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0xb80e0c40: Failure in SSL library, usually a protocol error
D/OkHttp: error:1407742E:SSL routines:SSL23_GET_SERVER_HELLO:tlsv1 alert protocol version (external/openssl/ssl/s23_clnt.c:741 0x8d9dd990:0x00000000)
Я новичок в этом деле, скорее всего обращаю внимание не туда, перепробовал кучу методов, возможно они были рабочие, просто применял не так. Просьба помочь в решение вопроса. T_T
Самый верный способ решения проблемы - прекращение поддержки ОС меньше 5 версии.
Если всё же хочется сохранить поддержку старой и забагованной версии 4.х, то самый простой способ - с помощью гугла обновить сертификаты. Работать это будет, правда, только для девайсов, на которых гугловые сервисы есть.
Делается так:
/**
* Это должно фиксить SSLException
*
* @see {https://stackoverflow.com/a/42471738/3212712}
*/
private void updateAndroidSecurityProvider() {
try {
ProviderInstaller.installIfNeeded(this);
} catch (GooglePlayServicesRepairableException | GooglePlayServicesNotAvailableException e) {
// Thrown when Google Play Services is not installed, up-to-date, or enabled
// Show dialog to allow users to install, update, or otherwise enable Google Play services.
System.out.println("Google Play Services not available.");
}
}
Вызвать этот метод надо при старте приложения. В Application#onCreate()
или Activity#onCreate()
Есть ещё вот такой способ:
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
//https://gist.github.com/gokhangirgin/ac8fdb8843a70a420982
public class TLSSocketFactory extends SSLSocketFactory {
private SSLSocketFactory socketFactory;
public TLSSocketFactory() {
super();
try {
final SSLContext sContext = SSLContext.getInstance("TLSv1.2");
sContext.init(null, null, null);
socketFactory = sContext.getSocketFactory();
} catch (final NoSuchAlgorithmException | KeyManagementException e) {
System.out.println(e);;
}
}
@Override
public String[] getDefaultCipherSuites() {
return socketFactory.getDefaultCipherSuites();
}
@Override
public String[] getSupportedCipherSuites() {
return socketFactory.getSupportedCipherSuites();
}
@Override
public Socket createSocket(final Socket s, final String host, final int port, final boolean autoClose)
throws IOException {
final SSLSocket ss = (SSLSocket) socketFactory.createSocket(s, host, port, autoClose);
ss.setEnabledProtocols(ss.getSupportedProtocols());
ss.setEnabledCipherSuites(ss.getSupportedCipherSuites());
return ss;
}
@Override
public Socket createSocket(final String host, final int port) throws IOException {
final SSLSocket ss = (SSLSocket) socketFactory.createSocket(host, port);
ss.setEnabledProtocols(ss.getSupportedProtocols());
ss.setEnabledCipherSuites(ss.getSupportedCipherSuites());
return ss;
}
@Override
public Socket createSocket(final String host, final int port, final InetAddress localHost, final int localPort)
throws IOException {
final SSLSocket ss = (SSLSocket) socketFactory.createSocket(host, port, localHost, localPort);
ss.setEnabledProtocols(ss.getSupportedProtocols());
ss.setEnabledCipherSuites(ss.getSupportedCipherSuites());
return ss;
}
@Override
public Socket createSocket(final InetAddress host, final int port) throws IOException {
final SSLSocket ss = (SSLSocket) socketFactory.createSocket(host, port);
ss.setEnabledProtocols(ss.getSupportedProtocols());
ss.setEnabledCipherSuites(ss.getSupportedCipherSuites());
return ss;
}
@Override
public Socket createSocket(final InetAddress address, final int port, final InetAddress localAddress,
final int localPort) throws IOException {
final SSLSocket ss = (SSLSocket) socketFactory
.createSocket(address, port, localAddress, localPort);
ss.setEnabledProtocols(ss.getSupportedProtocols());
ss.setEnabledCipherSuites(ss.getSupportedCipherSuites());
return ss;
}
}
После чего применить класс выше в Application#onCreate()
//enable tls v1.2 for android < 21
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
HttpsURLConnection.setDefaultSSLSocketFactory(new TLSSocketFactory());
}
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Требуется перевести оператор switch в лямбда-выраженияДля этого нужно сделать Map(у) с возможными командами, и в зависимости от символа сделать...
Все классы подсветились оранжевым и написано что нет SDKSDK подключил 1
Только осваиваю Spring и, вот такая задача - нужно осуществить поиск по разным параметрамПричем параметры все не обязательные, т