I have a HTTPS MEDIA server with self signed certificate from which I want to stream audio in my Android app. As per this link from developer.android.com, to allow self signed certificate, I have generated a certificate by reading the .crt file, created a keystore with this certificate and initialized this keyStore to a TrustManagerFactory.
CertificateFactory cf = CertificateFactory.getInstance("X.509");
InputStream caInput = new BufferedInputStream(getResources().openRawResource(R.raw.certificate));
Certificate ca;
try {
ca = cf.generateCertificate(caInput);
Log.d(TAG, "ca=" + ((X509Certificate) ca).getSubjectDN());
} finally {
caInput.close();
}
// Create a KeyStore containing our trusted CAs
String keyStoreType = KeyStore.getDefaultType();
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);
// Create a TrustManager that trusts the CAs in our KeyStore
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);
// Create an SSLContext that uses our TrustManager
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, tmf.getTrustManagers(), null);
The link describes an example to use this custom SSLContext with an HttpsURLConnection object.
// Tell the URLConnection to use a SocketFactory from our SSLContext
URL url = new URL("https://certs.cac.washington.edu/CAtest/");
HttpsURLConnection urlConnection = (HttpsURLConnection)url.openConnection();
urlConnection.setSSLSocketFactory(context.getSocketFactory());
InputStream in = urlConnection.getInputStream();
But in my app for HTTP, I'm using MediaPlayer
class by setting the audio link as below.
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setDataSource(address); //address is a String variable like http://example.com/audio.aac
The question is, how do i use the above SSLContext's socketFactory
object with the MediaPlayer, so that the MediaPlayer could use HTTPS audio source.
To use this custom SSLContext
connection, we have to set the socketFactory
object to the HttpsURLConnection
before providing the source to the media player.
HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory());
This allows the MediaPlayer
to use the connection with our self signed certificate.
Other than this, I also had to provide a custom HostnameVerifier
implementation to verify the subjectAlternateNames manually.
final HostnameVerifier hv =
HttpsURLConnection.getDefaultHostnameVerifier();
HostnameVerifier hostnameVerifier = new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return hv.verify("www.youdomainname.com", session);
}
};
And this custom HostnameVerifier
could be linked to the MediaPlayer
by the below code.
HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);