B4A Library PndAudioExoPlayer - For online radio stations apps

Original library: https://github.com/google/ExoPlayer
Wrapper is based on ExoPlayer version v2.18.1 (22 Jul 2022)

This wrapper is not substitute for Erel's ExoPlayer, it was created with one goal in mind, to make it easier to create applications that use the online radio streams.

A few things have been added or made easier in relation to Erel's:
  • Handle audio focus - temporary mute player on call, SMS, etc.
  • Player's user agent
  • Radio station metadata
  • Stream metadata
  • Show song name, artist and album art (image) on remote Bluetooth device
  • Control player from remote device (smart watch, car's steering wheel, headphones, etc.)
  • Audio session ID for future improvements.

Some of the data you can extract from metadata: radio station name, song name, bitrate, radio station genre, radio station's url, etc.
Library can be used in Activity/B4XPage/Service.
Requires: B4A v11.5+, minSdkVersion: 21+

Screenshot.png

This is how example app looks on my Samsung (Tizen) watch, similar look and same functionality on Android and Huawei watches:
img.jpg

If you use non secure HTTP protocol for streams, you need to add this code in manifest:
B4X:
CreateResourceFromFile(Macro, Core.NetworkClearText)

PndAudioExoPlayer

Author:
Author: Google - B4a Wrapper: Pendrush
Version: 1.30
  • PndAudioExoPlayer
    • Events:
      • MediaSessionOnButton (KeyCode As Int)
      • MediaSessionOnPause
      • MediaSessionOnPlay
      • MediaSessionOnStop
      • OnAudioSessionIdChanged (AudioSessionId As Int)
      • OnIsPlayingChanged (IsPlaying As Boolean)
      • OnMetadata (Metadata As String)
      • OnPlaybackStateChanged (PlaybackState As Int)
      • OnPlayerError (Error As String)
      • OnTracksChanged (Metadata As String)
    • Functions:
      • AudioSessionId As Int
        Returns the audio session identifier.
      • HlsMediaSource (Url As String)
        For: HLS streams (stream Url ends with .m3u8)
        Url - Radio station stream Url
      • Initialize (EventName As String, UserAgent As String, HandleAudioFocus As Boolean, AllowCrossProtocolRedirects As Boolean)
        Initialize player.
        EventName - Event name.
        UserAgent - User agent of player.
        HandleAudioFocus - Whether the player should handle audio focus, for example temporary mute player on call, SMS, etc.
        AllowCrossProtocolRedirects - Allow redirect from HTTPS to HTTP and vice versa.
        PndAudioExoPlayer1.Initialize("PndAudioExoPlayer1", "MyAppUserAgent/1.0", True, True)
      • IsInitialized As Boolean
      • IsPlaying As Boolean
        Returns whether the player is playing.
      • Play
        Resumes playback.
      • ProgressiveMediaSource (Url As String)
        For: MPEG (MP3), AAC, OGG streams
        Url - Radio station stream Url
      • Release
        Releases the player.
        This method must be called when the player is no longer required.
        The player must not be used after calling this method.
      • Stop
        Stops playback.
      • UpdateMediaSession (KeyTitle As String, KeyArtist As String, KeyAlbumArt As android.graphics.Bitmap)
        This items will display on remote (bluetooth) device like: smart watch, car display, etc.
        KeyTitle - Title name or song name
        KeyArtist - Artist name or for example radio station name
        KeyAlbumArt- Image of album or for example radio station logo.
    • Properties:
      • Volume As Float
        Get or Sets the audio volume.
        Range(from = 0.0, to = 1.0)

What's new:

v1.30
  • ExoPlayer library v2.18.1 (22 Jul 2022)
  • Event name renamed from OnTracksInfoChanged to OnTracksChanged (event name is changed in original ExoPlayer library).
  • Example app updated, with new event, notification (foreground service) and PartialLock to prevent system to kill app/service.
v1.21
  • Resolved conflict with RuntimePermissions library.
  • Example app updated, removed AppCompat library.
v1.20
  • Previous, Next and all other media buttons will rise new event MediaSessionOnButton (KeyCode As Int)
  • Example app updated
v1.10
  • UpdateMediaSession - Title, song name and album art for remote devices like: smart watch, car display, etc.
  • 3 new events for remote devices (Bluetooth): play, pause, stop, this also should work from headphone devices. You can use it FROM remote device to control player on your phone, volume also work from remote device.

Download library from: https://www.dropbox.com/s/p1l6ixw758r68wt/PndAudioExoPlayerLibrary.zip?dl=0
 

Attachments

  • PndAudioExoPlayerExample.zip
    101.6 KB · Views: 278
Last edited:
I have good news for The author of this library. I can 100 % confirm, that even BLuetooth headset HBFS900 is fully compatible with The library and with The sample app. I can use next / Previous Hbs900 Bluetooth headset to switch between The stations. Also Play / Pause button work smoothly. I have also done my best to solve issue, that if user turn off The device screen, playback could stop on some aggressive Android setups, which have been focused on energy saving.
I have used starter.bas to add The simple code. Sure, it may have disadvantage. That background service will be started immediately after app execution even before user will play AN station. Some advanced developers here would know how to fix it. Some programmers simply solve such situations by enforcing ignore battery optimisations permission and to call special intent to recall battery optimisation enforcing dialog. But The service based approach is more ellegant so I rather want to use service based approach. I Am sending servicestarter.bas as attachment.
 

Attachments

  • Starter.bas
    1,007 bytes · Views: 151
Dear Pendrush,
I have A big plea to you.
Is it possible to extend your library, so audio meta data could be obtained even if live Internet radio stream is not being actually plaied by Exoplayer? Or unfortunately, Exoplayer from Google company have been coded by The way, which prevent from doing so?
My aim of this plea is to allow Internet radio player programmer to allow programmer to play The specified song?
GUI could contain Editable field with The hint enter song name. And if user fill out The song name, app could monitor meta data of The specified live stream. If The specified song will be plaied, app could start play.
I Am aware, that I want too advanced and complex features.
I also know, that there are professional companies, who are using their own servers for such thinks to monitor many live Internet streams for user given song. So I AM aware, that I could not monitor too much streams at The same time for meta data on my own device.
I would want to only monitor one live stream.
But if it is not possible also because os Internet technology used in live streams, I will understand that.

Your library has brought much joy to Me as a visually impaired advanced user with no sight at all.
I can make several little Internet radio players for myselves thanks to your code and library.
I do not have to cope with object position values, I can even used my wired or bluetooth headsets to switch between live streams. I Am really very very happy thanks to your programmers work dear Pendrush. And I Am really appreciating your time and your development Java and Android API deep knowledge very much. I Am meaning it from The bottom of my heart.

So thank you very very much for your very useful and stable library.
 
Dear elite developers,
Who of us could try to add some miracle code to The ServicePlayer service so it will allow even users or Android 12 to be able to listen live stream with The screen turned off.
Why I Am asking for such miracle code?
Because Even ignore battery optimisations are not The guarantee, that you will be able to listen live streams with screen turned off on Android 9 and newer.
So who of us could modify sample code from The creator of this forum thread, so radio player will not be turned off even on Android 12 with The screen turned off and if AC adapter is not connected to The device.


It is really very painful Android world today.
Why Google apps such as Youtube Music premium or Youtube Premium are able to overcome power management?
Does Google use some their undocumented secret APi functions for such purposes?

If yes, may be, that The founder of B4A could try to negotiate with engineers from Google so their secret APIS could be The part of some B4A library such as Phone library.
 
Dear specialists,
Please, is it really necessary to add some album picture name as argument to The following function?
PndAudioExoPlayer1.UpdateMediaSession(SongName, StationName, ExampleAlbumArt.Get(CurentStationId))
If I do not add albumart, argument is mandatory so function do not allow Me to update media session.
Library is really 100 % perfect. Thank you for adding audio focus detection so live stream is stopped when AN app such as Skype, Messenger, Whatsapp play incoming call, ETC. Library is also very stable.
 
Dear elite developers and users.
I AM sending a modified original Pndexoplayer example to allow never ending playback. It is my amateour attempt based on The little Internet radio player based on original REL Exoplayer library. Player was named as MyLocation.
Without this code, I would be never able to create foreground service, Partial wakelock. If I have done something wrong, which will make services not stable, please repair it and let us know.
I can play Internet radio streams fluently for many many hours on Android newer than 6.0. I must test it on Android 11 and newer.
Here is modified project from The author of PNDaudioexoplayer library and example.
I Am hoping, that someone can have atleast a little benefit from my experiment. Foreground services are very important not only for live Internet audio streams playback.
 

Attachments

  • PndAudioExoPlayer_foreground_service.zip
    92.1 KB · Views: 133
PndAudioExoPlayer1.UpdateMediaSession(SongName, StationName, null)
Reliably and smoothly replaced even album bitmap. So very good instruction.
 
Original library: https://github.com/google/ExoPlayer
Wrapper is based on ExoPlayer version v2.18.1 (22 Jul 2022)

This wrapper is not substitute for Erel's ExoPlayer, it was created with one goal in mind, to make it easier to create applications that use the online radio streams.

A few things have been added or made easier in relation to Erel's:
  • Handle audio focus - temporary mute player on call, SMS, etc.
  • Player's user agent
  • Radio station metadata
  • Stream metadata
  • Show song name, artist and album art (image) on remote Bluetooth device
  • Control player from remote device (smart watch, car's steering wheel, headphones, etc.)
  • Audio session ID for future improvements.

Some of the data you can extract from metadata: radio station name, song name, bitrate, radio station genre, radio station's url, etc.
Library can be used in Activity/B4XPage/Service.
Requires: B4A v11.5+, minSdkVersion: 21+

View attachment 126778

This is how example app looks on my Samsung (Tizen) watch, similar look and same functionality on Android and Huawei watches:
View attachment 126719

If you use non secure HTTP protocol for streams, you need to add this code in manifest:
B4X:
CreateResourceFromFile(Macro, Core.NetworkClearText)



What's new:

v1.30
  • ExoPlayer library v2.18.1 (22 Jul 2022)
  • Event name renamed from OnTracksInfoChanged to OnTracksChanged (event name is changed in original ExoPlayer library).
  • Example app updated, with new event, notification (foreground service) and PartialLock to prevent system to kill app/service.
v1.21
  • Resolved conflict with RuntimePermissions library.
  • Example app updated, removed AppCompat library.
v1.20
  • Previous, Next and all other media buttons will rise new event MediaSessionOnButton (KeyCode As Int)
  • Example app updated
v1.10
  • UpdateMediaSession - Title, song name and album art for remote devices like: smart watch, car display, etc.
  • 3 new events for remote devices (Bluetooth): play, pause, stop, this also should work from headphone devices. You can use it FROM remote device to control player on your phone, volume also work from remote device.

Download library from: https://www.dropbox.com/s/p1l6ixw758r68wt/PndAudioExoPlayerLibrary.zip?dl=0
Very well done. You have managed services on really
professional level. Service is being stopped correctly. And you have managed FOreground service to always state. You hae even prepared excellent notification. Song name is The part of notification of your sample player. Really excellent sample app update. Now it is possible to create fully professional Internet radio player. It is only needed to recode special radio-browser.info Java library to B4A, conbine it with your sample app and professional Internet radio player can be created by every advanced forum members of this excellent community.
So Pendrush, very well done. And thank you for Exoplayer library update, which always reflect Exoplayer library update. Your approach to services is very instructive approach for every B4A forum meber, who would like to manage foreground services professionally.
 

Pendrush

Well-Known Member
Licensed User
Longtime User
Could you please explain briefly or through code snippet how this is done?
You just need to connect device to device via bluetooth.
Code (events) are in example app.
Part of code from example app:
B4X:
Private Sub PndAudioExoPlayer1_MediaSessionOnPause 'event raised from external devices like: smart watch, headphones play/pause button, remote control, etc.
    Log("MediaSessionOnPause")
    Stop
End Sub

Private Sub PndAudioExoPlayer1_MediaSessionOnPlay 'event raised from external devices like: smart watch, headphones play/pause button, remote control, etc.
    Log("MediaSessionOnPlay")
    Play
End Sub

Private Sub PndAudioExoPlayer1_MediaSessionOnStop 'event raised from external devices like: smart watch, headphones play/pause button, remote control, etc.
    Log("MediaSessionOnStop")
    Stop
End Sub

' in this event you can get keycode from remote device
Private Sub PndAudioExoPlayer1_MediaSessionOnButton (KeyCode As Int) 'event raised from external devices like: smart watch, headphones play/pause button, remote control, etc.
    If KeyCode = KeyCodes.KEYCODE_MEDIA_PREVIOUS Then
        Log ("MediaSessionOnButton PREVIOUS")
        PreviousStation
    Else if KeyCode = KeyCodes.KEYCODE_MEDIA_NEXT Then
        Log ("MediaSessionOnButton NEXT")
        NextStation
    End If
End Sub
 
Dear elite B4A developers,
If I will be using Timer to prevent some very power energy saving devices to suspend my apps. Do you think, that I can use timer without not being afraid, that my ARM AArch64 CPU will not be burned out?
If my timer body procedure will be empty and if I set timer tick to 1 Milliseconds. Is it secure for ARM CPU?
I believe, that Android kernel and some other Android binary modules are being using Timer also. But I Am giving this question for a security.

Pndaudioexoplayer example is very good example how to create The foreground service in combination with The Wakelock. But even if Android developer will be using so good approach, some devices can still auto suspend your player or other background running app.
So I have added timer to The example app.
But I need to know, if I can not burn out The CPU accidentally.
Thank you very much for your answer.
 
Top