How to play background music through all activities using Kotlin? - android

How can I play a music file in the background through all activities by using Kotlin? I have looked everywhere but I only found solutions for Java not for Kotlin.
I tried using this function but I don't know how to use it:
fun playSound() {
try {
if (m.isPlaying()) {
m.stop()
m.release()
//m = MediaPlayer()
}
val descriptor = assets.openFd("backgroundsound1.mp3")
m.setDataSource(descriptor.fileDescriptor, descriptor.startOffset, descriptor.length)
descriptor.close()
m.prepare()
m.setVolume(1f, 1f)
m.setLooping(true)
m.start()
} catch (e: Exception) {
e.printStackTrace()
}
}

Here' code in kotlin code Play background music in all activities
class BackgroundSoundService : Service() {
internal lateinit var player: MediaPlayer
override fun onBind(arg0: Intent): IBinder? {
return null
}
override fun onCreate() {
super.onCreate()
val afd = applicationContext.assets.openFd("backgroundsound1.wav") as AssetFileDescriptor
val player = MediaPlayer()
player.setDataSource(afd.fileDescriptor)
player.isLooping = true // Set looping
player.setVolume(100f, 100f)
}
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
player.start()
return 1
}
override fun onStart(intent: Intent, startId: Int) {
// TO DO
}
fun onUnBind(arg0: Intent): IBinder? {
// TO DO Auto-generated method
return null
}
fun onStop() {
}
fun onPause() {
}
override fun onDestroy() {
player.stop()
player.release()
}
override fun onLowMemory() {
}
companion object {
private val TAG: String? = null
}
}

Related

getting context is nullpoint exception even though tried many solutions in service

I'm trying to get context in service. I know that Service extends Context and I can get it at onCreate method. So I tried it and got error. I don't understand other example uses the context at onCreate and works, but not to me. Also I registered my service. the error is occurred at this line in service.
player = ExoPlayerFactory.newSimpleInstance(mContext, DefaultTrackSelector())
Why the context is null even though I initialized the context in onCreate? I saw the similar problem at here Android getContext on a background Service
error
java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.Context android.content.Context.getApplicationContext()' on a null object reference
activity
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
val musicPlayer = binding.musicPlayer
musicPlayer.player = audioService.getplayerInstance()
musicPlayer.player.playWhenReady = true
mIntent = Intent(this,AudioService::class.java)
Util.startForegroundService(this,mIntent)
bindService(mIntent, mConnection, Context.BIND_AUTO_CREATE);
initializePlayer();
}
Service
class AudioService : Service() {
private val mBinder: IBinder =Binder()
private var player: SimpleExoPlayer? = null
private var playerNotificationManager: PlayerNotificationManager? = null
private var cacheDataSourceFactory : CacheDataSourceFactory?=null
var mContext: Context? = null
override fun onDestroy() {
releasePlayer()
super.onDestroy()
}
override fun onCreate() {
super.onCreate()
mContext = this
if (player == null) {
startPlayer()
}
}
private fun releasePlayer() {
if (player != null) {
playerNotificationManager!!.setPlayer(null)
player!!.release()
player = null
}
}
override fun onBind(intent: Intent?): IBinder {
return mBinder
}
fun getplayerInstance(): SimpleExoPlayer? {
if (player == null) {
startPlayer()
}
return player
}
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
return START_STICKY
}
private fun startPlayer() {
val uri: Uri = Uri.parse("https://storage.googleapis.com/exoplayer-test-media-0/Jazz_In_Paris.mp3")
player = ExoPlayerFactory.newSimpleInstance(mContext, DefaultTrackSelector())
cacheDataSourceFactory = getCacheDataSourceFactory(mContext!!)
val mediaSource: MediaSource = ProgressiveMediaSource.Factory(cacheDataSourceFactory)
.createMediaSource(uri)
player!!.prepare(mediaSource)
player!!.setPlayWhenReady(true)
playerNotificationManager = PlayerNotificationManager.createWithNotificationChannel(
mContext,"channel_id", com.haii.exoplayerdemo.R.string.channelName,com.haii.exoplayerdemo.R.string.channelDescription,11,
object : PlayerNotificationManager.MediaDescriptionAdapter{
override fun createCurrentContentIntent(player: Player): PendingIntent? {
val intent = Intent(mContext,MainActivity::class.java)
return PendingIntent.getActivity(mContext,0,intent,PendingIntent.FLAG_UPDATE_CURRENT)
}
override fun getCurrentContentText(player: Player): String? {
return "description"
}
override fun getCurrentContentTitle(player: Player): String {
return "title"
}
override fun getCurrentLargeIcon(
player: Player,
callback: PlayerNotificationManager.BitmapCallback
): Bitmap? {
return null
}
} ,
object : PlayerNotificationManager.NotificationListener {
override fun onNotificationStarted(notificationId: Int, notification: Notification) {
Log.d("TAG","onNotificationStarted")
startForeground(notificationId,notification)
}
override fun onNotificationPosted(notificationId: Int, notification: Notification, ongoing: Boolean) {
Log.d("TAG","onNotificationPosted")
// startForeground(notificationId,notification)
}
override fun onNotificationCancelled(notificationId: Int, dismissedByUser: Boolean) {
Log.e("TAG","onNotificationCancelled 2")
stopSelf()
}
override fun onNotificationCancelled(notificationId: Int) {
Log.e("TAG","onNotificationCancelled 1")
// stopSelf()
}
}
)
playerNotificationManager!!.setPlayer(player)
}
fun getCacheDataSourceFactory(context : Context) : com.haii.exoplayerdemo.CacheDataSourceFactory?{
if(cacheDataSourceFactory==null){
cacheDataSourceFactory = com.haii.exoplayerdemo.CacheDataSourceFactory(
context,
DefaultDataSourceFactory(context, "ua"),
MyExoPlayer.MAX_CACHE_VALUE, MyExoPlayer.MAX_CACHE_FILE_VALUE
)
}
return cacheDataSourceFactory
}
}
I`m refering from here https://developer.android.com/guide/components/services.
The thing that you are doing wrong is calling getPlayerInstance() before onCreate is called. Your oncreate is called when you either bind or start the service. Good luck

Binding exoplayer from service to activity not working?

Following is my service class
class LocalAudioService : Service() {
var player: SimpleExoPlayer? = null
private var playerNotificationManager: PlayerNotificationManager? = null
private var mediaSession: MediaSessionCompat? = null
private var mediaSessionConnector: MediaSessionConnector? = null
private var allInOneApplication: AllInOneApplication? = null
private val binder = LocalBinder()
override fun onDestroy() {
mediaSession?.release()
mediaSessionConnector?.setPlayer(null, null)
playerNotificationManager?.setPlayer(null)
player?.release()
player = null
super.onDestroy()
}
override fun onBind(p0: Intent?): IBinder? {
return binder
}
fun getPlayerInstance(): SimpleExoPlayer? {
if (player == null) {
startPlayer()
}
return player
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
if(player == null){
startPlayer()
}
return START_STICKY
}
private fun startPlayer(){
val videoTrackSelectionFactory = AdaptiveTrackSelection.Factory()
val trackSelector = DefaultTrackSelector(this, videoTrackSelectionFactory)
allInOneApplication = AllInOneApplication.getInstance()
val renderersFactory = (application as AllInOneApplication).buildRenderersFactory(false)
player =
SimpleExoPlayer.Builder(this, renderersFactory).setTrackSelector(trackSelector).build()
val dataSourceFactory = DefaultDataSourceFactory(
this,
Util.getUserAgent(this, getString(R.string.app_name))
)
// val cacheDataSourceFactory = CacheDataSourceFactory(
// DownloadUtil.getCache(this),
// dataSourceFactory,
// CacheDataSource.FLAG_IGNORE_CACHE_ON_ERROR
// )
val concatenatingMediaSource = ConcatenatingMediaSource()
allInOneApplication?.localAudios?.map {
val mediaSource = ProgressiveMediaSource.Factory(dataSourceFactory)
.createMediaSource(it?.audioUri)
concatenatingMediaSource.addMediaSource(mediaSource)
}
player?.prepare(concatenatingMediaSource)
player?.playWhenReady = true
playerNotificationManager = PlayerNotificationManager.createWithNotificationChannel(
this,
AUDIO_CHANNEL_ID,
R.string.audio_channel_name,
R.string.audio_channel_name,
NOTIFICATION_ID,
object : MediaDescriptionAdapter {
override fun createCurrentContentIntent(player: Player): PendingIntent? {
val intent = Intent(this#LocalAudioService, LocalAudioPlayer::class.java)
return PendingIntent.getActivity(
this#LocalAudioService,
0,
intent,
PendingIntent.FLAG_UPDATE_CURRENT
)
}
override fun getCurrentContentText(player: Player): CharSequence? {
return allInOneApplication?.localAudios?.get(player.currentWindowIndex)?.title
}
override fun getCurrentContentTitle(player: Player): CharSequence {
return allInOneApplication?.localAudios?.get(player.currentWindowIndex)?.title.toString()
}
override fun getCurrentLargeIcon(
player: Player,
callback: PlayerNotificationManager.BitmapCallback
): Bitmap? {
return BitmapFactory.decodeResource(resources, R.drawable.audio)
}
}, object : PlayerNotificationManager.NotificationListener {
override fun onNotificationPosted(
notificationId: Int,
notification: Notification,
ongoing: Boolean
) {
startForeground(notificationId, notification)
}
override fun onNotificationCancelled(
notificationId: Int,
dismissedByUser: Boolean
) {
stopSelf()
}
}
)
playerNotificationManager?.setPlayer(player)
mediaSession = MediaSessionCompat(this, MEDIA_SESSION_TAG)
mediaSession?.isActive = true
mediaSession?.sessionToken?.let { playerNotificationManager?.setMediaSessionToken(it) }
mediaSessionConnector = MediaSessionConnector(mediaSession)
mediaSessionConnector?.setQueueNavigator(object : TimelineQueueNavigator(mediaSession) {
override fun getMediaDescription(
player: Player?,
windowIndex: Int
): MediaDescriptionCompat? {
return allInOneApplication?.getMediaDescription(
this#LocalAudioService,
allInOneApplication?.localAudios?.get(windowIndex)
)
}
})
mediaSessionConnector?.setPlayer(player, null)
}
inner class LocalBinder : Binder() {
val service: LocalAudioService
get() = this#LocalAudioService
}
}
Following is my Activity class
class LocalAudioPlayer : AppCompatActivity() {
private var localAudioService: LocalAudioService? = null
private var mBound = false
private val mConnection: ServiceConnection = object : ServiceConnection {
override fun onServiceConnected(componentName: ComponentName, iBinder: IBinder) {
val binder: LocalAudioService.LocalBinder = iBinder as LocalAudioService.LocalBinder
localAudioService = binder.service
mBound = true
initializePlayer()
}
override fun onServiceDisconnected(componentName: ComponentName) {
mBound = false
}
}
private fun initializePlayer() {
if (mBound) {
val player: SimpleExoPlayer? = localAudioService?.getPlayerInstance()
exoplayer_local_audio_player.player = player
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_local_audio_player)
Intent(this,LocalAudioService::class.java).also {
Util.startForegroundService(this,it)
exoplayer_local_audio_player.useController = true
exoplayer_local_audio_player.showController()
exoplayer_local_audio_player.controllerAutoShow = true
exoplayer_local_audio_player.controllerHideOnTouch = false
}
}
override fun onStart() {
super.onStart()
bindService(intent,mConnection, Context.BIND_AUTO_CREATE)
initializePlayer()
//TODO do any UI setup
}
override fun onStop() {
unbindService(mConnection)
mBound = false
super.onStop()
}
}
I tried following this question Binding PlayerView with SimpleExoPlayer from a service but the sole does not works for me
Try this:
override fun onStart() {
super.onStart()
Intent(this, LocalAudioService::class.java).also { intent ->
bindService(intent, mConnection, Context.BIND_AUTO_CREATE)
}
}
initializePlayer() should not be called here. At this moment the Service is not bound yet. When the service is bound it will called in the onServiceConnected callback.
bindService(intent,mConnection, Context.BIND_AUTO_CREATE)
intent is null here . Do Asure you are getting correct and non null intent.It should be global declared as in reference example
intent = new Intent(this, AudioPlayerService.class);
here intent is globally declared.

How to play multiple audio uri sequentially using exoplayer?

I am trying to play audio using exoplayer.
I have multiple files in a local directory and I want to play them sequentially. I am trying to add multiple to URIs to MediaSource, but I couldn't find the solution.
Here, the first file is playing correctly but none of the rest. I am using the ExoPlayer version 2.9.2
Note: In my case the files in the "Articles" folder will be updated dynamically while player is running.
Please suggest a solution. My code:
class AudioPlayerService : Service() {
private var player: SimpleExoPlayer? = null
private var playerNotificationManager: PlayerNotificationManager? = null
private var mediaSession: MediaSessionCompat? = null
private var mediaSessionConnector: MediaSessionConnector? = null
private var dataSourceFactory: DataSource.Factory? = null
private var extractorsFactory: ExtractorsFactory? = null
private var dynamicConcatenatingMediaSource: ConcatenatingMediaSource? = null
override fun onCreate() {
super.onCreate()
val context: Context = this
player = ExoPlayerFactory.newSimpleInstance(this)
dataSourceFactory = DefaultDataSourceFactory(context, BuildConfig.APPLICATION_ID)
extractorsFactory = DefaultExtractorsFactory()
var file: File = File(Environment.getExternalStorageDirectory().absolutePath + "/Articles")
/*for (i in file.listFiles()){
Log.e("","" +file.listFiles())
}*/
var uri =
Uri.parse(Environment.getExternalStorageDirectory().absolutePath + "/Articles" + "/article_tts" + 0 + ".wav")
//if (dynamicConcatenatingMediaSource == null)
dynamicConcatenatingMediaSource = ConcatenatingMediaSource()
val mediaSource: MediaSource =
ExtractorMediaSource.Factory(dataSourceFactory).createMediaSource(uri)
dynamicConcatenatingMediaSource?.addMediaSource(mediaSource)
player?.prepare(dynamicConcatenatingMediaSource)
player?.setPlayWhenReady(true)
player?.addListener(object : Player.EventListener {
override fun onTracksChanged(
trackGroups: TrackGroupArray?,
trackSelections: TrackSelectionArray?
) {
}
override fun onPlayerError(error: ExoPlaybackException?) {
stopSelf()
}
override fun onLoadingChanged(isLoading: Boolean) {
}
override fun onPositionDiscontinuity(reason: Int) {
}
override fun onRepeatModeChanged(repeatMode: Int) {
}
override fun onShuffleModeEnabledChanged(shuffleModeEnabled: Boolean) {
}
override fun onTimelineChanged(timeline: Timeline?, manifest: Any?, reason: Int) {
}
override fun onPlayerStateChanged(playWhenReady: Boolean, playbackState: Int) {
if (playbackState == Player.STATE_ENDED) {
player?.stop()
stopSelf()
}
}
override fun onSeekProcessed() {
}
override fun onPlaybackParametersChanged(playbackParameters: PlaybackParameters?) {
}
})
playerNotificationManager = PlayerNotificationManager.createWithNotificationChannel(
context,
"playback_channel",
R.string.playback_channel_name,
7001,
object : MediaDescriptionAdapter {
override fun getCurrentContentTitle(player: Player): String {
return "Playlist"
}
override fun createCurrentContentIntent(player: Player): PendingIntent? {
return null
}
override fun getCurrentContentText(player: Player): String? {
return "Playlist Demo"
}
override fun getCurrentLargeIcon(
player: Player,
callback: BitmapCallback
): Bitmap? {
return getBitmap(context, R.drawable.ic_vikatan_logo_new)
}
}
)
playerNotificationManager?.setNotificationListener(object :
PlayerNotificationManager.NotificationListener {
override fun onNotificationStarted(
notificationId: Int,
notification: Notification
) {
startForeground(notificationId, notification)
}
override fun onNotificationCancelled(notificationId: Int) {
stopSelf()
}
})
playerNotificationManager?.setPriority(NotificationCompat.PRIORITY_HIGH);
playerNotificationManager?.setUseNavigationActions(false)
playerNotificationManager?.setFastForwardIncrementMs(0)
playerNotificationManager?.setRewindIncrementMs(0)
playerNotificationManager?.setUsePlayPauseActions(true);
playerNotificationManager?.setPlayer(player)
mediaSession = MediaSessionCompat(context, "audio")
mediaSession?.setActive(true)
playerNotificationManager?.setMediaSessionToken(mediaSession?.getSessionToken())
mediaSessionConnector = MediaSessionConnector(mediaSession)
mediaSessionConnector?.setQueueNavigator(object : TimelineQueueNavigator(mediaSession) {
override fun getMediaDescription(
player: Player,
windowIndex: Int
): MediaDescriptionCompat {
return getMediaDescription(context)
}
})
mediaSessionConnector?.setPlayer(player, null)
}
override fun onDestroy() {
mediaSession!!.release()
mediaSessionConnector!!.setPlayer(null, null)
playerNotificationManager!!.setPlayer(null)
player!!.release()
player = null
super.onDestroy()
}
override fun onBind(intent: Intent?): IBinder? {
return null
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
return START_STICKY
}
fun getBitmap(context: Context, #DrawableRes bitmapResource: Int): Bitmap {
return (context.resources.getDrawable(bitmapResource) as BitmapDrawable).bitmap
}
fun getMediaDescription(context: Context?): MediaDescriptionCompat {
val extras = Bundle()
val bitmap: Bitmap = getBitmap(context!!, R.drawable.ic_vikatan_logo_new)
extras.putParcelable(
MediaMetadataCompat.METADATA_KEY_ALBUM_ART,
bitmap
)
extras.putParcelable(
MediaMetadataCompat.METADATA_KEY_DISPLAY_ICON,
bitmap
)
return MediaDescriptionCompat.Builder()
.setMediaId("audio_id")
.setIconBitmap(bitmap)
.setTitle("Playlist")
.setDescription("Playlist Demo")
.setExtras(extras)
.build()
}
}
Use the concatenating media source.
private val concatenatingMediaSource = ConcatenatingMediaSource()
Then create separate mediasource for each audio file and add to concatenatingMediaSource by using
concatenatingMediaSource.addMediaSource(your_media_source_object)

IllegalStateException: Unable to retrieve AudioTrack pointer for write()

I am using a third-party text-to-speech tool to make my app ADA compliant. I am using this service to speak text every time text needs to be dictated:
class TTSService : Service() {
private val ttsUtils = TTSUtils.getInstance(this)
private val voiceText = ttsUtils.voiceText
private lateinit var audioTrack:AudioTrack
override fun onBind(intent: Intent?): IBinder? {
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
audioTrack = AudioTrack(
AudioManager.USE_DEFAULT_STREAM_TYPE,
IVTDefine.SAMPLE_RATE_16000,
AudioFormat.CHANNEL_OUT_MONO,
AudioFormat.ENCODING_PCM_16BIT,
71296,
AudioTrack.MODE_STREAM
)
if (ttsUtils.isEnabled) {
ttsUtils.getEngineVoice()
if (null == voiceText) {
return START_STICKY
}
audioTrack.play()
try {
Thread(Runnable {
voiceText.vtapiTextToBuffer(intent?.getStringExtra("TextToSpeak"), //Library method that turns text string into audioTrack of
object : VoiceTextListener {
override fun onReadBufferWithWordInfo(output: ByteArray?, outputSize: Int, wordInfo: MutableList<SyncWordInfo>?) {
}
override fun onReadBuffer(output: ByteArray?, outputSize: Int) {
if (outputSize > 0) {
val audioData = ByteBuffer.wrap(output)
audioTrack.write(audioData, audioData.remaining(), AudioTrack.WRITE_BLOCKING)
}
}
override fun onReadBufferWithMarkInfo(output: ByteArray?, outputSize: Int, markInfo: MutableList<SyncMarkInfo>?) {
}
override fun onError(error: String?) {
Log.e(TAG, "Error: $error")
}
})
}).start()
} catch (e: java.lang.Exception) {
e.printStackTrace()
}
}
return START_REDELIVER_INTENT
}
override fun onDestroy() {
super.onDestroy()
voiceText.vtapiStopBuffer()
if (audioTrack.playState == AudioTrack.PLAYSTATE_PLAYING) {
try {
audioTrack.pause()
} catch (e: Exception) {
AppLog.e(TAG, e.message!!)
}
}
try {
audioTrack.flush()
audioTrack.release()
} catch (e: Exception) {
AppLog.e(TAG, e.message!!)
}
}
}
The service is always started with this method in another class:
fun speakText(textToSpeak: String) {
val i = Intent(mContext, TTSService::class.java)
i.putExtra("TextToSpeak", textToSpeak)
mContext.stopService(i)
mContext.startService(i)
}
I'm getting the above error when audioTrack.write() is called in the service's runnable, but I don't know what the error means. How do I make sure it's retrieving the pointer?

Notification Icon from URL Exoplayer

I am trying to set the notification icon in my player which is using exoplayer. I have a playlist and am using concatenatingMediaSource. I have the url of the album art for every song but I dont know how I can set it as the notification icon. I read some answers which suggested using a AsyncTask and creating the notification onPostExecute() but I don't see how I can do in exoplayer playerNotificationManager.
Here is my Audio Service class:-
class AudioPlayerService: Service() {
private var player: SimpleExoPlayer? = null
private var playerNotificationManager: PlayerNotificationManager? = null
private var mediaSession: MediaSessionCompat? = null
private var mediaSessionConnector: MediaSessionConnector? = null
private var songList: ArrayList<MetaData>? = null
private var context: Context? = null
override fun onCreate() {
super.onCreate()
context = this
val descriptionAdapter = object : PlayerNotificationManager.MediaDescriptionAdapter {
override fun getCurrentContentTitle(player: Player?): String {
return songList!![player!!.currentWindowIndex].name
}
override fun getCurrentContentText(player: Player?): String? {
return songList!![player!!.currentWindowIndex].artist
}
override fun getCurrentLargeIcon(player: Player?, callback: PlayerNotificationManager.BitmapCallback?): Bitmap? {
return null
}
override fun createCurrentContentIntent(player: Player?): PendingIntent? {
val intent = Intent(context, MainActivity::class.java)
return PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
}
}
playerNotificationManager = PlayerNotificationManager.createWithNotificationChannel(
this, "1", R.string.notification_name, 1, descriptionAdapter
)
val notificationListener = object : PlayerNotificationManager.NotificationListener {
override fun onNotificationStarted(notificationId: Int, notification: Notification?) {
startForeground(notificationId, notification)
}
override fun onNotificationCancelled(notificationId: Int) {
stopSelf()
}
}
playerNotificationManager!!.setNotificationListener(
notificationListener
)
mediaSession = MediaSessionCompat(context, "Test")
mediaSession!!.isActive = true
playerNotificationManager!!.setMediaSessionToken(mediaSession!!.sessionToken)
mediaSessionConnector = MediaSessionConnector(mediaSession)
val timelineQueueNavigator = object: TimelineQueueNavigator(mediaSession) {
override fun getMediaDescription(player: Player?, windowIndex: Int): MediaDescriptionCompat {
return getMediaDescription(songList!![windowIndex])
}
}
mediaSessionConnector!!.setQueueNavigator(timelineQueueNavigator)
}
override fun onDestroy() {
super.onDestroy()
mediaSession!!.release()
mediaSessionConnector!!.setPlayer(null, null)
playerNotificationManager!!.setPlayer(null)
player!!.release()
player = null
}
override fun onBind(p0: Intent?): IBinder? {
return null
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
songList = intent!!.getParcelableArrayListExtra<MetaData>("list")
context = this
player = ExoPlayerFactory.newSimpleInstance(this, DefaultTrackSelector())
val dataSource = DefaultDataSourceFactory(
this, Util.getUserAgent(this, getString(R.string.app_name)))
val concatenatingMediaSource = ConcatenatingMediaSource()
for(item in songList!!){
val mediaSource = ExtractorMediaSource.Factory(dataSource)
.createMediaSource(Uri.parse(item.url))
concatenatingMediaSource.addMediaSource(mediaSource)
}
player!!.prepare(concatenatingMediaSource)
player!!.playWhenReady = true
playerNotificationManager!!.setPlayer(player)
mediaSessionConnector!!.setPlayer(player, null)
return START_STICKY
}
private fun getMediaDescription(item: MetaData): MediaDescriptionCompat {
return MediaDescriptionCompat.Builder()
.setMediaId(item.id.toString())
.setTitle(item.name)
.setDescription(item.artist)
.setMediaUri(Uri.parse(item.url))
.build()
}
}
Thanks in advance.
You can use Glide for it in overrided function getCurrentLargeIcon
override fun getCurrentLargeIcon(
player: Player?,
callback: PlayerNotificationManager.BitmapCallback?
): Bitmap? {
loadBitmap(currentStation?.cover, callback)
return null //or stub image
}
private fun loadBitmap(url: String, callback: PlayerNotificationManager.BitmapCallback?) {
Glide.with(this)
.asBitmap()
.load(url)
.into(object : CustomTarget<Bitmap>() {
override fun onResourceReady(
resource: Bitmap,
transition: Transition<in Bitmap>?
) {
callback?.onBitmap(resource)
}
})
}
You need to override it like this
#Nullable
#Override
public Bitmap getCurrentLargeIcon(Player player, PlayerNotificationManager.BitmapCallback callback) {
Glide.with(this)
.asBitmap()
.load(uri)
.into(new CustomTarget<Bitmap>() {
#Override
public void onResourceReady(#NonNull Bitmap resource, #Nullable Transition<? super Bitmap> transition) {
callback.onBitmap(resource);
}
#Override
public void onLoadCleared(#Nullable Drawable placeholder) {
}
});
return null;
}

Categories

Resources