add media session & update exo player to 2.14.0

This commit is contained in:
Jannik 2021-06-12 20:57:12 +02:00
parent 0decf317d9
commit 1d071eafdb
Signed by: Seil0
GPG Key ID: E8459F3723C52C24
3 changed files with 45 additions and 23 deletions

View File

@ -11,7 +11,7 @@ android {
minSdkVersion 23 minSdkVersion 23
targetSdkVersion 30 targetSdkVersion 30
versionCode 4180 //00.04.100 versionCode 4180 //00.04.100
versionName "0.4.2-alpha1" versionName "0.4.2-alpha2"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
resValue "string", "build_time", buildTime() resValue "string", "build_time", buildTime()
@ -55,10 +55,11 @@ dependencies {
implementation 'com.google.android.material:material:1.3.0' implementation 'com.google.android.material:material:1.3.0'
implementation 'com.google.code.gson:gson:2.8.7' implementation 'com.google.code.gson:gson:2.8.7'
implementation 'com.google.android.exoplayer:exoplayer-core:2.13.3' implementation 'com.google.android.exoplayer:exoplayer-core:2.14.0'
implementation 'com.google.android.exoplayer:exoplayer-hls:2.13.3' implementation 'com.google.android.exoplayer:exoplayer-hls:2.14.0'
implementation 'com.google.android.exoplayer:exoplayer-dash:2.13.3' implementation 'com.google.android.exoplayer:exoplayer-dash:2.14.0'
implementation 'com.google.android.exoplayer:exoplayer-ui:2.13.3' implementation 'com.google.android.exoplayer:exoplayer-ui:2.14.0'
implementation 'com.google.android.exoplayer:extension-mediasession:2.14.0'
implementation 'org.jsoup:jsoup:1.13.1' implementation 'org.jsoup:jsoup:1.13.1'
implementation 'com.github.bumptech.glide:glide:4.12.0' implementation 'com.github.bumptech.glide:glide:4.12.0'

View File

@ -26,9 +26,7 @@ import com.google.android.exoplayer2.ui.StyledPlayerControlView
import com.google.android.exoplayer2.util.Util import com.google.android.exoplayer2.util.Util
import kotlinx.android.synthetic.main.activity_player.* import kotlinx.android.synthetic.main.activity_player.*
import kotlinx.android.synthetic.main.player_controls.* import kotlinx.android.synthetic.main.player_controls.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.mosad.teapod.R import org.mosad.teapod.R
import org.mosad.teapod.preferences.Preferences import org.mosad.teapod.preferences.Preferences
import org.mosad.teapod.ui.components.EpisodesListPlayer import org.mosad.teapod.ui.components.EpisodesListPlayer
@ -187,7 +185,7 @@ class PlayerActivity : AppCompatActivity() {
* set play when ready and listeners * set play when ready and listeners
*/ */
private fun initExoPlayer() { private fun initExoPlayer() {
model.player.addListener(object : Player.EventListener { model.player.addListener(object : Player.Listener {
override fun onPlaybackStateChanged(state: Int) { override fun onPlaybackStateChanged(state: Int) {
super.onPlaybackStateChanged(state) super.onPlaybackStateChanged(state)
@ -208,7 +206,7 @@ class PlayerActivity : AppCompatActivity() {
} }
} }
}) })
// start playing the current episode, after all needed player components have been initialized // start playing the current episode, after all needed player components have been initialized
model.playEpisode(model.currentEpisode, true) model.playEpisode(model.currentEpisode, true)
} }
@ -256,30 +254,26 @@ class PlayerActivity : AppCompatActivity() {
timerUpdates = Timer().scheduleAtFixedRate(0, 500) { timerUpdates = Timer().scheduleAtFixedRate(0, 500) {
lifecycleScope.launch { lifecycleScope.launch {
var btnNextEpIsVisible: Boolean val btnNextEpIsVisible = button_next_ep.isVisible
var controlsVisible: Boolean val controlsVisible = controller.isVisible
withContext(Dispatchers.Main) { if (model.player.duration > 0) {
if (model.player.duration > 0) { remainingTime = model.player.duration - model.player.currentPosition
remainingTime = model.player.duration - model.player.currentPosition remainingTime = if (remainingTime < 0) 0 else remainingTime
remainingTime = if (remainingTime < 0) 0 else remainingTime
}
btnNextEpIsVisible = button_next_ep.isVisible
controlsVisible = controller.isVisible
} }
if (remainingTime in 1..20000) { if (remainingTime in 1..20000) {
// if the next ep button is not visible, make it visible. Don't show in pip mode // 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()) { if (!btnNextEpIsVisible && model.nextEpisode != null && Preferences.autoplay && !isInPiPMode()) {
withContext(Dispatchers.Main) { showButtonNextEp() } showButtonNextEp()
} }
} else if (btnNextEpIsVisible) { } else if (btnNextEpIsVisible) {
withContext(Dispatchers.Main) { hideButtonNextEp() } hideButtonNextEp()
} }
// if controls are visible, update them // if controls are visible, update them
if (controlsVisible) { if (controlsVisible) {
withContext(Dispatchers.Main) { updateControls() } updateControls()
} }
} }
} }

View File

@ -2,12 +2,15 @@ package org.mosad.teapod.ui.activity.player
import android.app.Application import android.app.Application
import android.net.Uri import android.net.Uri
import android.support.v4.media.session.MediaSessionCompat
import android.support.v4.media.session.PlaybackStateCompat
import android.util.Log import android.util.Log
import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.google.android.exoplayer2.C import com.google.android.exoplayer2.C
import com.google.android.exoplayer2.MediaItem import com.google.android.exoplayer2.MediaItem
import com.google.android.exoplayer2.SimpleExoPlayer 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.MediaSource
import com.google.android.exoplayer2.source.hls.HlsMediaSource import com.google.android.exoplayer2.source.hls.HlsMediaSource
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory
@ -23,6 +26,7 @@ import org.mosad.teapod.util.Media
import java.util.* import java.util.*
import kotlin.collections.ArrayList import kotlin.collections.ArrayList
/** /**
* PlayerViewModel handles all stuff related to media/episodes. * PlayerViewModel handles all stuff related to media/episodes.
* When currentEpisode is changed the player will start playing it (not initial media), * 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) { class PlayerViewModel(application: Application) : AndroidViewModel(application) {
val player = SimpleExoPlayer.Builder(application).build() 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 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) var media: Media = Media(-1, "", DataTypes.MediaType.OTHER)
internal set internal set
@ -45,13 +52,30 @@ class PlayerViewModel(application: Application) : AndroidViewModel(application)
var currentLanguage: Locale = Locale.ROOT var currentLanguage: Locale = Locale.ROOT
internal set internal set
init {
initMediaSession()
}
override fun onCleared() { override fun onCleared() {
super.onCleared() super.onCleared()
mediaSession.release()
player.release() player.release()
Log.d(javaClass.name, "Released player") 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) { fun loadMedia(mediaId: Int, episodeId: Int) {
runBlocking { runBlocking {
media = AoDParser.getMediaById(mediaId) 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) { fun playMedia(source: MediaSource, replace: Boolean = false, seekPosition: Long = 0) {
if (replace || player.contentDuration == C.TIME_UNSET) { if (replace || player.contentDuration == C.TIME_UNSET) {
player.setMediaSource(source) player.setMediaSource(source)