Я работаю над приложением радио, использующим Exoplayer.В случае этого подкаста Exoplayer генерирует SSLHandshakeException.
Чтобы это исправить, я попытался:
1.Обновите провайдера безопасности с помощью установщика провайдера, позвонив по номеру ProviderInstaller.installIfNeededAsync
.
public class MainActivity extends Activity
implements ProviderInstaller.ProviderInstallListener {
private static final int ERROR_DIALOG_REQUEST_CODE = 1;
private boolean mRetryProviderInstall;
//Update the security provider when the activity is created.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ProviderInstaller.installIfNeededAsync(this, this);
}
/**
* This method is only called if the provider is successfully
updated (or is already up-to-date).
*/
@Override
protected void onProviderInstalled() {
// Provider is up-to-date, app can make secure network calls.
}
/**
* This method is called if updating fails; the error code indicates
* whether the error is recoverable.
*/
@Override
protected void onProviderInstallFailed(int errorCode, Intent recoveryIntent) {
GoogleApiAvailability availability = GoogleApiAvailability.getInstance();
if (availability.isUserRecoverableError(errorCode)) {
// Recoverable error. Show a dialog prompting the user to
// install/update/enable Google Play services.
availability.showErrorDialogFragment(
this,
errorCode,
ERROR_DIALOG_REQUEST_CODE,
new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
// The user chose not to take the recovery action
onProviderInstallerNotAvailable();
}
});
} else {
// Google Play services is not available.
onProviderInstallerNotAvailable();
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode,
Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == ERROR_DIALOG_REQUEST_CODE) {
// Adding a fragment via GoogleApiAvailability.showErrorDialogFragment
// before the instance state is restored throws an error. So instead,
// set a flag here, which will cause the fragment to delay until
// onPostResume.
mRetryProviderInstall = true;
}
}
/**
* On resume, check to see if we flagged that we need to reinstall the provider.
*/
@Override
protected void onPostResume() {
super.onPostResume();
if (mRetryProviderInstall) {
// We can now safely retry installation.
ProviderInstaller.installIfNeededAsync(this, this);
}
mRetryProviderInstall = false;
}
private void onProviderInstallerNotAvailable() {
// This is reached if the provider cannot be updated for some reason.
// App should consider all HTTP communication to be vulnerable,
// and take appropriate action.
}
}
2.Замените https на http
В этом случае Exoplayer выдает исключение с кодом ошибки 308 (исключение перенаправления).
3.Используйте NetCipher вместо HttpUrlConnection, вызвав HttpsURLConnection connection = NetCipher.getHttpsURLConnection(sourceUrl)
, как описано здесь
4.Используйте NoSSLv3SocketFactory , как описано здесь
5.Отключите проверку сертификата SSL , позвонив по номеру
private static void disableSSLCertificateChecking() {
TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return null;
}
@Override
public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
// Not implemented
}
@Override
public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
// Not implemented
}
} };
try {
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
} catch (KeyManagementException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
6.Создать customTrust
Чтобы получить сертификаты, я запускаю команду open ssl:
OpenSSL> s_client -connect simplecast.com:443
7.Загрузите файл .crt с здесь и, как Google предлагает запустить
CertificateFactory cf = CertificateFactory.getInstance("X.509");
InputStream caInput = new BufferedInputStream(new
FileInputStream("my_downloaded.crt"));
Certificate ca;
try {
ca = cf.generateCertificate(caInput);
System.out.println("ca=" + ((X509Certificate) ca).getSubjectDN());
} finally {
caInput.close();
}
String keyStoreType = KeyStore.getDefaultType();
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, tmf.getTrustManagers(), null);
// Tell the URLConnection to use a SocketFactory from our SSLContext
HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
urlConnection.setSSLSocketFactory(context.getSocketFactory());
8.Включите только TLSv1.2 , используя код из здесь
Устройство, которое я использую для тестирования, - Samsung SM-t111 Android 4.2.2.На нем установлены сервисы Google Play, но я пытаюсь решить проблему без использования сервисов Google Play, потому что на устройстве клиента его нет.
Подскажите, пожалуйста, какое должно быть рабочее решение?