add pip support to player activity

This commit is contained in:
Jannik 2021-01-06 15:07:31 +01:00
parent a0111d45cf
commit e5037cf9ac
Signed by: Seil0
GPG Key ID: E8459F3723C52C24
2 changed files with 72 additions and 10 deletions

View File

@ -21,16 +21,19 @@
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter> </intent-filter>
</activity> </activity>
<activity
android:name=".player.PlayerActivity"
android:label="@string/app_name"
android:theme="@style/PlayerTheme"
android:configChanges="orientation|screenSize|layoutDirection" />
<activity <activity
android:name=".MainActivity" android:name=".MainActivity"
android:label="@string/app_name" android:label="@string/app_name"
android:screenOrientation="portrait"> android:screenOrientation="portrait">
</activity> </activity>
<activity
android:name=".player.PlayerActivity"
android:parentActivityName=".MainActivity"
android:label="@string/app_name"
android:theme="@style/PlayerTheme"
android:supportsPictureInPicture="true"
android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|layoutDirection">
</activity>
</application> </application>
</manifest> </manifest>

View File

@ -3,11 +3,16 @@ package org.mosad.teapod.player
import android.animation.Animator import android.animation.Animator
import android.animation.AnimatorListenerAdapter import android.animation.AnimatorListenerAdapter
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.app.PictureInPictureParams
import android.content.pm.PackageManager
import android.content.res.Configuration
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.util.Log import android.util.Log
import android.util.Rational
import android.view.* import android.view.*
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.GestureDetectorCompat import androidx.core.view.GestureDetectorCompat
import androidx.core.view.isVisible import androidx.core.view.isVisible
@ -73,6 +78,11 @@ class PlayerActivity : AppCompatActivity() {
initActions() initActions()
} }
/**
* once minimum is android 7.0 this can be simplified
* only onStart and onStop should be needed then
* see: https://developer.android.com/guide/topics/ui/picture-in-picture#continuing_playback
*/
override fun onStart() { override fun onStart() {
super.onStart() super.onStart()
if (Util.SDK_INT > 23) { if (Util.SDK_INT > 23) {
@ -83,6 +93,8 @@ class PlayerActivity : AppCompatActivity() {
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
if (isInPiPMode()) { return }
if (Util.SDK_INT <= 23) { if (Util.SDK_INT <= 23) {
initPlayer() initPlayer()
video_view?.onResume() video_view?.onResume()
@ -91,6 +103,8 @@ class PlayerActivity : AppCompatActivity() {
override fun onPause() { override fun onPause() {
super.onPause() super.onPause()
if (isInPiPMode()) { return }
if (Util.SDK_INT <= 23) { if (Util.SDK_INT <= 23) {
video_view?.onPause() video_view?.onPause()
releasePlayer() releasePlayer()
@ -112,6 +126,38 @@ class PlayerActivity : AppCompatActivity() {
super.onSaveInstanceState(outState) super.onSaveInstanceState(outState)
} }
/**
* previous to android n, don't override
*/
@RequiresApi(Build.VERSION_CODES.N)
override fun onUserLeaveHint() {
super.onUserLeaveHint()
// start pip mode, if supported
if (packageManager.hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE)) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
@Suppress("deprecation")
enterPictureInPictureMode()
} else {
val width = model.player.videoFormat?.width ?: 0
val height = model.player.videoFormat?.height ?: 0
val params = PictureInPictureParams.Builder()
.setAspectRatio(Rational(width, height))
.build()
enterPictureInPictureMode(params)
}
}
}
override fun onPictureInPictureModeChanged(isInPictureInPictureMode: Boolean, newConfig: Configuration?) {
super.onPictureInPictureModeChanged(isInPictureInPictureMode, newConfig)
// Hide the full-screen UI (controls, etc.) while in picture-in-picture mode.
if (isInPictureInPictureMode) {
controller.hideImmediately()
}
}
private fun initPlayer() { private fun initPlayer() {
if (model.media.id < 0) { if (model.media.id < 0) {
Log.e(javaClass.name, "No media was set.") Log.e(javaClass.name, "No media was set.")
@ -178,7 +224,9 @@ class PlayerActivity : AppCompatActivity() {
} }
private fun initActions() { private fun initActions() {
exo_close_player.setOnClickListener { this.finish() } exo_close_player.setOnClickListener {
this.finish()
}
rwd_10.setOnButtonClickListener { rewind() } rwd_10.setOnButtonClickListener { rewind() }
ffwd_10.setOnButtonClickListener { fastForward() } ffwd_10.setOnButtonClickListener { fastForward() }
button_next_ep.setOnClickListener { playNextEpisode() } button_next_ep.setOnClickListener { playNextEpisode() }
@ -213,8 +261,8 @@ class PlayerActivity : AppCompatActivity() {
} }
if (remainingTime in 1..20000) { if (remainingTime in 1..20000) {
// if the next ep button is not visible, make it visible // if the next ep button is not visible, make it visible. Don't show in pip mode
if (!btnNextEpIsVisible && model.nextEpisode != null && Preferences.autoplay) { if (!btnNextEpIsVisible && model.nextEpisode != null && Preferences.autoplay && !isInPiPMode()) {
withContext(Dispatchers.Main) { showButtonNextEp() } withContext(Dispatchers.Main) { showButtonNextEp() }
} }
} else if (btnNextEpIsVisible) { } else if (btnNextEpIsVisible) {
@ -229,7 +277,7 @@ class PlayerActivity : AppCompatActivity() {
} }
} }
private fun releasePlayer(){ private fun releasePlayer() {
playbackPosition = model.player.currentPosition playbackPosition = model.player.currentPosition
currentWindow = model.player.currentWindowIndex currentWindow = model.player.currentWindowIndex
playWhenReady = model.player.playWhenReady playWhenReady = model.player.playWhenReady
@ -378,6 +426,14 @@ class PlayerActivity : AppCompatActivity() {
pauseAndHideControls() pauseAndHideControls()
} }
private fun isInPiPMode(): Boolean {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
isInPictureInPictureMode
} else {
false // pip mode not supported
}
}
/** /**
* pause playback and hide controls * pause playback and hide controls
*/ */
@ -393,7 +449,10 @@ class PlayerActivity : AppCompatActivity() {
* on single tap hide or show the controls * on single tap hide or show the controls
*/ */
override fun onSingleTapConfirmed(e: MotionEvent?): Boolean { override fun onSingleTapConfirmed(e: MotionEvent?): Boolean {
if (controller.isVisible) controller.hide() else controller.show() if (!isInPiPMode()) {
if (controller.isVisible) controller.hide() else controller.show()
}
return true return true
} }