add media session & update exo player to 2.14.0
This commit is contained in:
		@ -26,9 +26,7 @@ import com.google.android.exoplayer2.ui.StyledPlayerControlView
 | 
			
		||||
import com.google.android.exoplayer2.util.Util
 | 
			
		||||
import kotlinx.android.synthetic.main.activity_player.*
 | 
			
		||||
import kotlinx.android.synthetic.main.player_controls.*
 | 
			
		||||
import kotlinx.coroutines.Dispatchers
 | 
			
		||||
import kotlinx.coroutines.launch
 | 
			
		||||
import kotlinx.coroutines.withContext
 | 
			
		||||
import org.mosad.teapod.R
 | 
			
		||||
import org.mosad.teapod.preferences.Preferences
 | 
			
		||||
import org.mosad.teapod.ui.components.EpisodesListPlayer
 | 
			
		||||
@ -187,7 +185,7 @@ class PlayerActivity : AppCompatActivity() {
 | 
			
		||||
     * set play when ready and listeners
 | 
			
		||||
     */
 | 
			
		||||
    private fun initExoPlayer() {
 | 
			
		||||
        model.player.addListener(object : Player.EventListener {
 | 
			
		||||
        model.player.addListener(object : Player.Listener {
 | 
			
		||||
            override fun onPlaybackStateChanged(state: Int) {
 | 
			
		||||
                super.onPlaybackStateChanged(state)
 | 
			
		||||
 | 
			
		||||
@ -208,7 +206,7 @@ class PlayerActivity : AppCompatActivity() {
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
        
 | 
			
		||||
        // start playing the current episode, after all needed player components have been initialized
 | 
			
		||||
        model.playEpisode(model.currentEpisode, true)
 | 
			
		||||
    }
 | 
			
		||||
@ -256,30 +254,26 @@ class PlayerActivity : AppCompatActivity() {
 | 
			
		||||
 | 
			
		||||
        timerUpdates = Timer().scheduleAtFixedRate(0, 500) {
 | 
			
		||||
            lifecycleScope.launch {
 | 
			
		||||
                var btnNextEpIsVisible: Boolean
 | 
			
		||||
                var controlsVisible: Boolean
 | 
			
		||||
                val btnNextEpIsVisible = button_next_ep.isVisible
 | 
			
		||||
                val controlsVisible = controller.isVisible
 | 
			
		||||
 | 
			
		||||
                withContext(Dispatchers.Main) {
 | 
			
		||||
                    if (model.player.duration > 0) {
 | 
			
		||||
                        remainingTime = model.player.duration - model.player.currentPosition
 | 
			
		||||
                        remainingTime = if (remainingTime < 0) 0 else remainingTime
 | 
			
		||||
                    }
 | 
			
		||||
                    btnNextEpIsVisible = button_next_ep.isVisible
 | 
			
		||||
                    controlsVisible = controller.isVisible
 | 
			
		||||
                if (model.player.duration > 0) {
 | 
			
		||||
                    remainingTime = model.player.duration - model.player.currentPosition
 | 
			
		||||
                    remainingTime = if (remainingTime < 0) 0 else remainingTime
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (remainingTime in 1..20000) {
 | 
			
		||||
                    // if the next ep button is not visible, make it visible. Don't show in pip mode
 | 
			
		||||
                    if (!btnNextEpIsVisible && model.nextEpisode != null && Preferences.autoplay && !isInPiPMode()) {
 | 
			
		||||
                        withContext(Dispatchers.Main) { showButtonNextEp() }
 | 
			
		||||
                        showButtonNextEp()
 | 
			
		||||
                    }
 | 
			
		||||
                } else if (btnNextEpIsVisible) {
 | 
			
		||||
                    withContext(Dispatchers.Main) { hideButtonNextEp() }
 | 
			
		||||
                    hideButtonNextEp()
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // if controls are visible, update them
 | 
			
		||||
                if (controlsVisible) {
 | 
			
		||||
                    withContext(Dispatchers.Main) { updateControls() }
 | 
			
		||||
                    updateControls()
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -2,12 +2,15 @@ package org.mosad.teapod.ui.activity.player
 | 
			
		||||
 | 
			
		||||
import android.app.Application
 | 
			
		||||
import android.net.Uri
 | 
			
		||||
import android.support.v4.media.session.MediaSessionCompat
 | 
			
		||||
import android.support.v4.media.session.PlaybackStateCompat
 | 
			
		||||
import android.util.Log
 | 
			
		||||
import androidx.lifecycle.AndroidViewModel
 | 
			
		||||
import androidx.lifecycle.viewModelScope
 | 
			
		||||
import com.google.android.exoplayer2.C
 | 
			
		||||
import com.google.android.exoplayer2.MediaItem
 | 
			
		||||
import com.google.android.exoplayer2.SimpleExoPlayer
 | 
			
		||||
import com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector
 | 
			
		||||
import com.google.android.exoplayer2.source.MediaSource
 | 
			
		||||
import com.google.android.exoplayer2.source.hls.HlsMediaSource
 | 
			
		||||
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory
 | 
			
		||||
@ -23,6 +26,7 @@ import org.mosad.teapod.util.Media
 | 
			
		||||
import java.util.*
 | 
			
		||||
import kotlin.collections.ArrayList
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * PlayerViewModel handles all stuff related to media/episodes.
 | 
			
		||||
 * When currentEpisode is changed the player will start playing it (not initial media),
 | 
			
		||||
@ -31,10 +35,13 @@ import kotlin.collections.ArrayList
 | 
			
		||||
class PlayerViewModel(application: Application) : AndroidViewModel(application) {
 | 
			
		||||
 | 
			
		||||
    val player = SimpleExoPlayer.Builder(application).build()
 | 
			
		||||
    val dataSourceFactory = DefaultDataSourceFactory(application, Util.getUserAgent(application, "Teapod"))
 | 
			
		||||
    private val dataSourceFactory = DefaultDataSourceFactory(application, Util.getUserAgent(application, "Teapod"))
 | 
			
		||||
    private val mediaSession = MediaSessionCompat(application, "TEAPOD_PLAYER_SESSION")
 | 
			
		||||
 | 
			
		||||
    lateinit var mStateBuilder: PlaybackStateCompat
 | 
			
		||||
 | 
			
		||||
    val currentEpisodeChangedListener = ArrayList<() -> Unit>()
 | 
			
		||||
    val preferredLanguage = if (Preferences.preferSecondary) Locale.JAPANESE else Locale.GERMAN
 | 
			
		||||
    private val preferredLanguage = if (Preferences.preferSecondary) Locale.JAPANESE else Locale.GERMAN
 | 
			
		||||
 | 
			
		||||
    var media: Media = Media(-1, "", DataTypes.MediaType.OTHER)
 | 
			
		||||
        internal set
 | 
			
		||||
@ -45,13 +52,30 @@ class PlayerViewModel(application: Application) : AndroidViewModel(application)
 | 
			
		||||
    var currentLanguage: Locale = Locale.ROOT
 | 
			
		||||
        internal set
 | 
			
		||||
 | 
			
		||||
    init {
 | 
			
		||||
        initMediaSession()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun onCleared() {
 | 
			
		||||
        super.onCleared()
 | 
			
		||||
 | 
			
		||||
        mediaSession.release()
 | 
			
		||||
        player.release()
 | 
			
		||||
 | 
			
		||||
        Log.d(javaClass.name, "Released player")
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * set the media session to active
 | 
			
		||||
     * create a media session connector to set title and description
 | 
			
		||||
     */
 | 
			
		||||
    private fun initMediaSession() {
 | 
			
		||||
        val mediaSessionConnector = MediaSessionConnector(mediaSession)
 | 
			
		||||
        mediaSessionConnector.setPlayer(player)
 | 
			
		||||
 | 
			
		||||
        mediaSession.isActive = true
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun loadMedia(mediaId: Int, episodeId: Int) {
 | 
			
		||||
        runBlocking {
 | 
			
		||||
            media = AoDParser.getMediaById(mediaId)
 | 
			
		||||
@ -115,6 +139,9 @@ class PlayerViewModel(application: Application) : AndroidViewModel(application)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * change the players media source and start playback
 | 
			
		||||
     */
 | 
			
		||||
    fun playMedia(source: MediaSource, replace: Boolean = false, seekPosition: Long = 0) {
 | 
			
		||||
        if (replace || player.contentDuration == C.TIME_UNSET) {
 | 
			
		||||
            player.setMediaSource(source)
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user