Since switching from Mediaplayer to a simple implementation Exoplayer I have noticed much improved load times but I'm wondering if there is any built in functionality such as a metadata change listener when streaming audio?
I have implemented Exoplayer using a simple example as below:
Uri uri = Uri.parse(url);
DefaultSampleSource sampleSource =
new DefaultSampleSource(new FrameworkSampleExtractor(context, uri, null), 2);
TrackRenderer audioRenderer = new MediaCodecAudioTrackRenderer(sampleSource);
mExoPlayerInstance.prepare(audioRenderer);
mExoPlayerInstance.setPlayWhenReady(true);
Posting to show the implementation that worked for me. Just a Singleton with start and stop methods and some intents to update the UI.
This will depend on a few factors (like stream format), but the short answer is no. Most browsers don't expose this. There is an out-of-band metadata approach though.
If the Icecast server from which you are getting this stream is running version 2.4.1 or newer, then you can query the metadata from its JSON API though. Basically by querying
http://icecast.example.org/status.json
or if you want info for only one specific stream:http://icecast.example.org/status.json?mount=/stream.ogg
This can be worked into older versions of Icecast, but then the API output needs to be cached by the webserver hosting the webpage/player or with CORS ACAO support.
Parsing the Shoutcast Metadata Protocol consists of two parts:
Part one can be done without OkHttp based on ExoPlayer 2.6.1 (in Kotlin):
Part two is more involved and posting all the code is a little to much. You might want to take a look at the ExoPlayer2 extension I created instead:
github.com/saschpe/android-exoplayer2-ext-icy
It does not depend on OkHttp and is used in my Soma FM streaming radio application for Android called Alpha+ Player.
I have an AsyncTask that starts ExoPlayer from an IceCast Stream:
OkHttpDataSource is the class that implements HttpDataSource using OkHttpClient. It creates InputStream as a response from a request. I included this class from AACDecoder library https://github.com/vbartacek/aacdecoder-android/blob/master/decoder/src/com/spoledge/aacdecoder/IcyInputStream.java and replace InputStream with IcyInputStream depending on the response:
(In open() of OkHttpDataSource)
Now IcyInputStream can catch the medatada and invoke callback object (playerCallback here). PlayerCallback is also from the AACDecoder library: https://github.com/vbartacek/aacdecoder-android/blob/b58c519a341340a251f3291895c76ff63aef5b94/decoder/src/com/spoledge/aacdecoder/PlayerCallback.java
This way you are not making any duplicate stream and it is singular. If you don't want to have AACDecoder library in your project, then you can just copy needed files and include them directly in your project.