Browse Source

Merge pull request 'add media session & update exo player' (#41) from feature/pip-media-controls into develop

Reviewed-on: #41
pull/43/head
Jannik 1 year ago
parent
commit
5ccf907ed8
  1. 11
      app/build.gradle
  2. 34
      app/src/main/java/org/mosad/teapod/ui/activity/player/PlayerActivity.kt
  3. 27
      app/src/main/java/org/mosad/teapod/ui/activity/player/PlayerViewModel.kt

11
app/build.gradle

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

34
app/src/main/java/org/mosad/teapod/ui/activity/player/PlayerActivity.kt

@ -7,6 +7,7 @@ import android.app.PictureInPictureParams
import android.content.Intent
import android.content.pm.PackageManager
import android.content.res.Configuration
import android.graphics.Rect
import android.os.Build
import android.os.Bundle
import android.util.Log
@ -26,9 +27,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
@ -147,8 +146,15 @@ class PlayerActivity : AppCompatActivity() {
} else {
val width = model.player.videoFormat?.width ?: 0
val height = model.player.videoFormat?.height ?: 0
val contentFrame: View = video_view.findViewById(R.id.exo_content_frame)
val contentRect = with(contentFrame) {
val (x, y) = intArrayOf(0, 0).also(::getLocationInWindow)
Rect(x, y, x + width, y + height)
}
val params = PictureInPictureParams.Builder()
.setAspectRatio(Rational(width, height))
.setSourceRectHint(contentRect)
.build()
enterPictureInPictureMode(params)
}
@ -187,7 +193,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 +214,7 @@ class PlayerActivity : AppCompatActivity() {
}
}
})
// start playing the current episode, after all needed player components have been initialized
model.playEpisode(model.currentEpisode, true)
}
@ -256,30 +262,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()
}
}
}

27
app/src/main/java/org/mosad/teapod/ui/activity/player/PlayerViewModel.kt

@ -2,12 +2,14 @@ package org.mosad.teapod.ui.activity.player
import android.app.Application
import android.net.Uri
import android.support.v4.media.session.MediaSessionCompat
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
@ -31,10 +33,11 @@ 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")
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 +48,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 +135,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)

Loading…
Cancel
Save

Du besuchst diese Seite mit einem veralteten IPv4-Internetzugang. Möglicherweise treten in Zukunft Probleme mit der Erreichbarkeit und Performance auf. Bitte frage deinen Internetanbieter oder Netzwerkadministrator nach IPv6-Unterstützung.
You are visiting this site with an outdated IPv4 internet access. You may experience problems with accessibility and performance in the future. Please ask your ISP or network administrator for IPv6 support.
Weitere Infos | More Information
Klicke zum schließen | Click to close