fix #274, replace video MediaPlayer with ExoPlayer
This commit is contained in:
parent
ebaf64af70
commit
1038ee33d2
3 changed files with 158 additions and 137 deletions
|
@ -54,6 +54,7 @@ dependencies {
|
||||||
implementation 'pl.droidsonroids.gif:android-gif-drawable:1.2.12'
|
implementation 'pl.droidsonroids.gif:android-gif-drawable:1.2.12'
|
||||||
implementation 'com.github.chrisbanes:PhotoView:2.1.3'
|
implementation 'com.github.chrisbanes:PhotoView:2.1.3'
|
||||||
implementation 'com.android.support.constraint:constraint-layout:1.1.2'
|
implementation 'com.android.support.constraint:constraint-layout:1.1.2'
|
||||||
|
implementation 'com.google.android.exoplayer:exoplayer-core:2.8.2'
|
||||||
|
|
||||||
kapt "android.arch.persistence.room:compiler:1.1.1"
|
kapt "android.arch.persistence.room:compiler:1.1.1"
|
||||||
implementation "android.arch.persistence.room:runtime:1.1.1"
|
implementation "android.arch.persistence.room:runtime:1.1.1"
|
||||||
|
|
|
@ -1,21 +1,31 @@
|
||||||
package com.simplemobiletools.gallery.fragments
|
package com.simplemobiletools.gallery.fragments
|
||||||
|
|
||||||
|
import android.annotation.TargetApi
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
|
import android.graphics.Point
|
||||||
|
import android.graphics.SurfaceTexture
|
||||||
import android.media.AudioManager
|
import android.media.AudioManager
|
||||||
import android.media.MediaPlayer
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.support.annotation.RequiresApi
|
|
||||||
import android.util.DisplayMetrics
|
import android.util.DisplayMetrics
|
||||||
import android.view.*
|
import android.view.*
|
||||||
import android.view.animation.AnimationUtils
|
import android.view.animation.AnimationUtils
|
||||||
import android.widget.SeekBar
|
import android.widget.SeekBar
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
|
import com.google.android.exoplayer2.*
|
||||||
|
import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory
|
||||||
|
import com.google.android.exoplayer2.source.ExtractorMediaSource
|
||||||
|
import com.google.android.exoplayer2.source.TrackGroupArray
|
||||||
|
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector
|
||||||
|
import com.google.android.exoplayer2.trackselection.TrackSelectionArray
|
||||||
|
import com.google.android.exoplayer2.upstream.DataSource
|
||||||
|
import com.google.android.exoplayer2.upstream.DataSpec
|
||||||
|
import com.google.android.exoplayer2.upstream.FileDataSource
|
||||||
|
import com.google.android.exoplayer2.video.VideoListener
|
||||||
import com.simplemobiletools.commons.extensions.*
|
import com.simplemobiletools.commons.extensions.*
|
||||||
import com.simplemobiletools.commons.helpers.isJellyBean1Plus
|
import com.simplemobiletools.commons.helpers.isJellyBean1Plus
|
||||||
import com.simplemobiletools.gallery.BuildConfig
|
|
||||||
import com.simplemobiletools.gallery.R
|
import com.simplemobiletools.gallery.R
|
||||||
import com.simplemobiletools.gallery.activities.VideoActivity
|
import com.simplemobiletools.gallery.activities.VideoActivity
|
||||||
import com.simplemobiletools.gallery.extensions.*
|
import com.simplemobiletools.gallery.extensions.*
|
||||||
|
@ -24,32 +34,28 @@ import com.simplemobiletools.gallery.helpers.MediaSideScroll
|
||||||
import com.simplemobiletools.gallery.models.Medium
|
import com.simplemobiletools.gallery.models.Medium
|
||||||
import kotlinx.android.synthetic.main.pager_video_item.view.*
|
import kotlinx.android.synthetic.main.pager_video_item.view.*
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.IOException
|
|
||||||
|
|
||||||
class VideoFragment : ViewPagerFragment(), SurfaceHolder.Callback, SeekBar.OnSeekBarChangeListener {
|
class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, SeekBar.OnSeekBarChangeListener {
|
||||||
private val PROGRESS = "progress"
|
private val PROGRESS = "progress"
|
||||||
private val MIN_SKIP_LENGTH = 2000
|
private val MIN_SKIP_LENGTH = 2000
|
||||||
|
private val PLAY_PAUSE_VISIBLE_ALPHA = 0.8f
|
||||||
|
|
||||||
private var mMediaPlayer: MediaPlayer? = null
|
private var mTextureView: TextureView? = null
|
||||||
private var mSurfaceView: SurfaceView? = null
|
|
||||||
private var mSurfaceHolder: SurfaceHolder? = null
|
|
||||||
private var mCurrTimeView: TextView? = null
|
private var mCurrTimeView: TextView? = null
|
||||||
private var mTimerHandler: Handler? = null
|
private var mTimerHandler: Handler? = null
|
||||||
private var mSeekBar: SeekBar? = null
|
private var mSeekBar: SeekBar? = null
|
||||||
private var mTimeHolder: View? = null
|
private var mTimeHolder: View? = null
|
||||||
private var mView: View? = null
|
private var mView: View? = null
|
||||||
|
private var mExoPlayer: SimpleExoPlayer? = null
|
||||||
|
private var mVideoSize = Point(0, 0)
|
||||||
|
|
||||||
private var mIsPlaying = false
|
private var mIsPlaying = false
|
||||||
private var mIsDragged = false
|
private var mIsDragged = false
|
||||||
private var mIsFullscreen = false
|
private var mIsFullscreen = false
|
||||||
private var mIsFragmentVisible = false
|
private var mIsFragmentVisible = false
|
||||||
private var mPlayOnPrepare = false
|
private var mWasInit = false
|
||||||
private var wasEncoded = false
|
|
||||||
private var wasInit = false
|
|
||||||
private var isPrepared = false
|
|
||||||
private var mCurrTime = 0
|
private var mCurrTime = 0
|
||||||
private var mDuration = 0
|
private var mDuration = 0
|
||||||
private var mEncodedPath = ""
|
|
||||||
|
|
||||||
private var mStoredShowExtendedDetails = false
|
private var mStoredShowExtendedDetails = false
|
||||||
private var mStoredHideExtendedDetails = false
|
private var mStoredHideExtendedDetails = false
|
||||||
|
@ -77,7 +83,7 @@ class VideoFragment : ViewPagerFragment(), SurfaceHolder.Callback, SeekBar.OnSee
|
||||||
}
|
}
|
||||||
|
|
||||||
mIsFullscreen = activity!!.window.decorView.systemUiVisibility and View.SYSTEM_UI_FLAG_FULLSCREEN == View.SYSTEM_UI_FLAG_FULLSCREEN
|
mIsFullscreen = activity!!.window.decorView.systemUiVisibility and View.SYSTEM_UI_FLAG_FULLSCREEN == View.SYSTEM_UI_FLAG_FULLSCREEN
|
||||||
mView!!.video_play_outline.alpha = if (mIsFullscreen) 0f else 1f
|
mView!!.video_play_outline.alpha = if (mIsFullscreen) 0f else PLAY_PAUSE_VISIBLE_ALPHA
|
||||||
|
|
||||||
setupPlayer()
|
setupPlayer()
|
||||||
if (savedInstanceState != null) {
|
if (savedInstanceState != null) {
|
||||||
|
@ -85,7 +91,7 @@ class VideoFragment : ViewPagerFragment(), SurfaceHolder.Callback, SeekBar.OnSee
|
||||||
}
|
}
|
||||||
|
|
||||||
checkFullscreen()
|
checkFullscreen()
|
||||||
wasInit = true
|
mWasInit = true
|
||||||
|
|
||||||
mView!!.apply {
|
mView!!.apply {
|
||||||
brightnessSideScroll = video_brightness_controller
|
brightnessSideScroll = video_brightness_controller
|
||||||
|
@ -102,6 +108,65 @@ class VideoFragment : ViewPagerFragment(), SurfaceHolder.Callback, SeekBar.OnSee
|
||||||
video_duration.setOnClickListener { skip(true) }
|
video_duration.setOnClickListener { skip(true) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mExoPlayer = ExoPlayerFactory.newSimpleInstance(context, DefaultTrackSelector())
|
||||||
|
mExoPlayer!!.addListener(object : Player.EventListener {
|
||||||
|
override fun onPlaybackParametersChanged(playbackParameters: PlaybackParameters?) {}
|
||||||
|
|
||||||
|
override fun onSeekProcessed() {}
|
||||||
|
|
||||||
|
override fun onTracksChanged(trackGroups: TrackGroupArray?, trackSelections: TrackSelectionArray?) {}
|
||||||
|
|
||||||
|
override fun onPlayerError(error: ExoPlaybackException?) {
|
||||||
|
activity?.showErrorToast(error.toString())
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
when (playbackState) {
|
||||||
|
Player.STATE_READY -> videoPrepared()
|
||||||
|
Player.STATE_ENDED -> videoCompleted()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
mExoPlayer!!.addVideoListener(object : VideoListener {
|
||||||
|
override fun onVideoSizeChanged(width: Int, height: Int, unappliedRotationDegrees: Int, pixelWidthHeightRatio: Float) {
|
||||||
|
mVideoSize.x = width
|
||||||
|
mVideoSize.y = height
|
||||||
|
setVideoSize()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onRenderedFirstFrame() {}
|
||||||
|
})
|
||||||
|
|
||||||
|
val uri = Uri.fromFile(File(medium.path))
|
||||||
|
val dataSpec = DataSpec(uri)
|
||||||
|
val fileDataSource = FileDataSource()
|
||||||
|
try {
|
||||||
|
fileDataSource.open(dataSpec)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
activity?.showErrorToast(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
val factory = DataSource.Factory { fileDataSource }
|
||||||
|
val audioSource = ExtractorMediaSource(fileDataSource.uri, factory, DefaultExtractorsFactory(), null, null)
|
||||||
|
mExoPlayer!!.audioStreamType = AudioManager.STREAM_MUSIC
|
||||||
|
mExoPlayer!!.prepare(audioSource)
|
||||||
|
medium.path.getVideoResolution()?.apply {
|
||||||
|
mVideoSize.x = x
|
||||||
|
mVideoSize.y = y
|
||||||
|
setVideoSize()
|
||||||
|
}
|
||||||
|
|
||||||
return mView
|
return mView
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,26 +222,23 @@ class VideoFragment : ViewPagerFragment(), SurfaceHolder.Callback, SeekBar.OnSee
|
||||||
|
|
||||||
mView!!.video_play_outline.setOnClickListener { togglePlayPause() }
|
mView!!.video_play_outline.setOnClickListener { togglePlayPause() }
|
||||||
|
|
||||||
mSurfaceView = mView!!.video_surface
|
mTextureView = mView!!.video_surface
|
||||||
mSurfaceHolder = mSurfaceView!!.holder
|
mTextureView!!.setOnClickListener { toggleFullscreen() }
|
||||||
mSurfaceHolder!!.addCallback(this)
|
mTextureView!!.surfaceTextureListener = this
|
||||||
mSurfaceView!!.setOnClickListener { toggleFullscreen() }
|
|
||||||
mView!!.video_holder.setOnClickListener { toggleFullscreen() }
|
mView!!.video_holder.setOnClickListener { toggleFullscreen() }
|
||||||
|
|
||||||
initTimeHolder()
|
initTimeHolder()
|
||||||
checkExtendedDetails()
|
checkExtendedDetails()
|
||||||
initMediaPlayer()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setMenuVisibility(menuVisible: Boolean) {
|
override fun setMenuVisibility(menuVisible: Boolean) {
|
||||||
super.setMenuVisibility(menuVisible)
|
super.setMenuVisibility(menuVisible)
|
||||||
if (mIsFragmentVisible && !menuVisible) {
|
if (mIsFragmentVisible && !menuVisible) {
|
||||||
pauseVideo()
|
pauseVideo()
|
||||||
releaseMediaPlayer()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mIsFragmentVisible = menuVisible
|
mIsFragmentVisible = menuVisible
|
||||||
if (menuVisible && wasInit) {
|
if (menuVisible && mWasInit) {
|
||||||
initMediaPlayer()
|
|
||||||
if (context?.config?.autoplayVideos == true) {
|
if (context?.config?.autoplayVideos == true) {
|
||||||
playVideo()
|
playVideo()
|
||||||
}
|
}
|
||||||
|
@ -259,8 +321,8 @@ class VideoFragment : ViewPagerFragment(), SurfaceHolder.Callback, SeekBar.OnSee
|
||||||
private fun setupTimer() {
|
private fun setupTimer() {
|
||||||
activity!!.runOnUiThread(object : Runnable {
|
activity!!.runOnUiThread(object : Runnable {
|
||||||
override fun run() {
|
override fun run() {
|
||||||
if (mMediaPlayer != null && !mIsDragged && mIsPlaying) {
|
if (mExoPlayer != null && !mIsDragged && mIsPlaying) {
|
||||||
mCurrTime = mMediaPlayer!!.currentPosition / 1000
|
mCurrTime = (mExoPlayer!!.currentPosition / 1000).toInt()
|
||||||
mSeekBar!!.progress = mCurrTime
|
mSeekBar!!.progress = mCurrTime
|
||||||
mCurrTimeView!!.text = mCurrTime.getFormattedDuration()
|
mCurrTimeView!!.text = mCurrTime.getFormattedDuration()
|
||||||
}
|
}
|
||||||
|
@ -299,8 +361,6 @@ class VideoFragment : ViewPagerFragment(), SurfaceHolder.Callback, SeekBar.OnSee
|
||||||
if (activity == null || !isAdded)
|
if (activity == null || !isAdded)
|
||||||
return
|
return
|
||||||
|
|
||||||
initMediaPlayer()
|
|
||||||
|
|
||||||
mIsPlaying = !mIsPlaying
|
mIsPlaying = !mIsPlaying
|
||||||
if (mIsPlaying) {
|
if (mIsPlaying) {
|
||||||
playVideo()
|
playVideo()
|
||||||
|
@ -310,102 +370,59 @@ class VideoFragment : ViewPagerFragment(), SurfaceHolder.Callback, SeekBar.OnSee
|
||||||
}
|
}
|
||||||
|
|
||||||
fun playVideo() {
|
fun playVideo() {
|
||||||
if (mMediaPlayer != null && isPrepared) {
|
if (mExoPlayer == null) {
|
||||||
mIsPlaying = true
|
return
|
||||||
mMediaPlayer?.start()
|
|
||||||
} else {
|
|
||||||
mPlayOnPrepare = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (videoEnded()) {
|
||||||
|
setProgress(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
mIsPlaying = true
|
||||||
|
mExoPlayer?.playWhenReady = true
|
||||||
mView!!.video_play_outline.setImageDrawable(resources.getDrawable(R.drawable.img_pause_outline_big))
|
mView!!.video_play_outline.setImageDrawable(resources.getDrawable(R.drawable.img_pause_outline_big))
|
||||||
activity!!.window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
activity!!.window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun pauseVideo() {
|
private fun pauseVideo() {
|
||||||
|
if (mExoPlayer == null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
mIsPlaying = false
|
mIsPlaying = false
|
||||||
mMediaPlayer?.pause()
|
if (!videoEnded()) {
|
||||||
|
mExoPlayer?.playWhenReady = false
|
||||||
|
}
|
||||||
mView?.video_play_outline?.setImageDrawable(resources.getDrawable(R.drawable.img_play_outline_big))
|
mView?.video_play_outline?.setImageDrawable(resources.getDrawable(R.drawable.img_play_outline_big))
|
||||||
activity!!.window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
activity!!.window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun initMediaPlayer() {
|
private fun videoEnded() = mExoPlayer!!.currentPosition >= mExoPlayer!!.duration
|
||||||
if (mMediaPlayer != null || !mIsFragmentVisible) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
val mediumPath = if (wasEncoded) mEncodedPath else getPathToLoad(medium)
|
|
||||||
|
|
||||||
// this workaround is needed for example if the filename contains a colon
|
|
||||||
val fileUri = if (mediumPath.startsWith("/")) context!!.getFilePublicUri(File(mediumPath), BuildConfig.APPLICATION_ID) else Uri.parse(mediumPath)
|
|
||||||
try {
|
|
||||||
mMediaPlayer = MediaPlayer().apply {
|
|
||||||
setDataSource(context, fileUri)
|
|
||||||
setDisplay(mSurfaceHolder)
|
|
||||||
setOnCompletionListener { videoCompleted() }
|
|
||||||
setOnVideoSizeChangedListener { mediaPlayer, width, height -> setVideoSize() }
|
|
||||||
setOnPreparedListener { videoPrepared(it) }
|
|
||||||
setAudioStreamType(AudioManager.STREAM_MUSIC)
|
|
||||||
prepare()
|
|
||||||
}
|
|
||||||
} catch (e: IOException) {
|
|
||||||
mEncodedPath = Uri.encode(getPathToLoad(medium))
|
|
||||||
if (wasEncoded) {
|
|
||||||
releaseMediaPlayer()
|
|
||||||
} else {
|
|
||||||
wasEncoded = true
|
|
||||||
mMediaPlayer = null
|
|
||||||
initMediaPlayer()
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
|
||||||
releaseMediaPlayer()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun setProgress(seconds: Int) {
|
private fun setProgress(seconds: Int) {
|
||||||
mMediaPlayer!!.seekTo(seconds * 1000)
|
mExoPlayer!!.seekTo(seconds * 1000L)
|
||||||
mSeekBar!!.progress = seconds
|
mSeekBar!!.progress = seconds
|
||||||
mCurrTimeView!!.text = seconds.getFormattedDuration()
|
mCurrTimeView!!.text = seconds.getFormattedDuration()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addPreviewImage() {
|
private fun videoPrepared() {
|
||||||
mMediaPlayer!!.start()
|
if (mDuration == 0) {
|
||||||
mMediaPlayer!!.pause()
|
mDuration = (mExoPlayer!!.duration / 1000).toInt()
|
||||||
}
|
setupTimeHolder()
|
||||||
|
setProgress(mCurrTime)
|
||||||
|
|
||||||
private fun cleanup() {
|
if (mIsFragmentVisible && (context!!.config.autoplayVideos)) {
|
||||||
pauseVideo()
|
playVideo()
|
||||||
mCurrTimeView?.text = 0.getFormattedDuration()
|
}
|
||||||
releaseMediaPlayer()
|
|
||||||
mSeekBar?.progress = 0
|
|
||||||
mTimerHandler?.removeCallbacksAndMessages(null)
|
|
||||||
mSurfaceView = null
|
|
||||||
mSurfaceHolder?.removeCallback(this)
|
|
||||||
mSurfaceHolder = null
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun releaseMediaPlayer() {
|
|
||||||
mMediaPlayer?.setSurface(null)
|
|
||||||
mMediaPlayer?.release()
|
|
||||||
mMediaPlayer = null
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun videoPrepared(mediaPlayer: MediaPlayer) {
|
|
||||||
isPrepared = true
|
|
||||||
mDuration = mediaPlayer.duration / 1000
|
|
||||||
addPreviewImage()
|
|
||||||
setupTimeHolder()
|
|
||||||
setProgress(mCurrTime)
|
|
||||||
|
|
||||||
if (mIsFragmentVisible && (context!!.config.autoplayVideos || mPlayOnPrepare)) {
|
|
||||||
playVideo()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun videoCompleted() {
|
private fun videoCompleted() {
|
||||||
if (!isAdded) {
|
if (!isAdded || mExoPlayer == null) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mCurrTime = (mExoPlayer!!.duration / 1000).toInt()
|
||||||
if (listener?.videoEnded() == false && context!!.config.loopVideos) {
|
if (listener?.videoEnded() == false && context!!.config.loopVideos) {
|
||||||
playVideo()
|
playVideo()
|
||||||
} else {
|
} else {
|
||||||
|
@ -415,37 +432,42 @@ class VideoFragment : ViewPagerFragment(), SurfaceHolder.Callback, SeekBar.OnSee
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun surfaceCreated(holder: SurfaceHolder) {
|
private fun cleanup() {
|
||||||
mSurfaceHolder = holder
|
pauseVideo()
|
||||||
if (mIsFragmentVisible) {
|
mCurrTimeView?.text = 0.getFormattedDuration()
|
||||||
initMediaPlayer()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) {
|
|
||||||
if (width != 0 && height != 0 && mSurfaceView != null) {
|
|
||||||
setVideoSize()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun surfaceDestroyed(holder: SurfaceHolder) {
|
|
||||||
releaseMediaPlayer()
|
releaseMediaPlayer()
|
||||||
|
mSeekBar?.progress = 0
|
||||||
|
mTimerHandler?.removeCallbacksAndMessages(null)
|
||||||
|
mTextureView = null
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
|
private fun releaseMediaPlayer() {
|
||||||
|
mExoPlayer?.stop()
|
||||||
|
mExoPlayer?.release()
|
||||||
|
mExoPlayer = null
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSurfaceTextureSizeChanged(surface: SurfaceTexture?, width: Int, height: Int) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSurfaceTextureUpdated(surface: SurfaceTexture?) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSurfaceTextureDestroyed(surface: SurfaceTexture?): Boolean {
|
||||||
|
releaseMediaPlayer()
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSurfaceTextureAvailable(surface: SurfaceTexture?, width: Int, height: Int) {
|
||||||
|
mExoPlayer?.setVideoSurface(Surface(mTextureView!!.surfaceTexture))
|
||||||
|
}
|
||||||
|
|
||||||
|
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
|
||||||
private fun setVideoSize() {
|
private fun setVideoSize() {
|
||||||
if (mSurfaceHolder == null)
|
if (activity == null || mTextureView == null)
|
||||||
mSurfaceHolder = mSurfaceView!!.holder
|
|
||||||
|
|
||||||
if (activity == null || mSurfaceHolder == null || !mSurfaceHolder!!.surface.isValid)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
initMediaPlayer()
|
val videoProportion = mVideoSize.x.toFloat() / mVideoSize.y.toFloat()
|
||||||
if (mMediaPlayer == null) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
val videoProportion = mMediaPlayer!!.videoWidth.toFloat() / mMediaPlayer!!.videoHeight.toFloat()
|
|
||||||
val display = activity!!.windowManager.defaultDisplay
|
val display = activity!!.windowManager.defaultDisplay
|
||||||
val screenWidth: Int
|
val screenWidth: Int
|
||||||
val screenHeight: Int
|
val screenHeight: Int
|
||||||
|
@ -462,7 +484,7 @@ class VideoFragment : ViewPagerFragment(), SurfaceHolder.Callback, SeekBar.OnSee
|
||||||
|
|
||||||
val screenProportion = screenWidth.toFloat() / screenHeight.toFloat()
|
val screenProportion = screenWidth.toFloat() / screenHeight.toFloat()
|
||||||
|
|
||||||
mSurfaceView!!.layoutParams.apply {
|
mTextureView!!.layoutParams.apply {
|
||||||
if (videoProportion > screenProportion) {
|
if (videoProportion > screenProportion) {
|
||||||
width = screenWidth
|
width = screenWidth
|
||||||
height = (screenWidth.toFloat() / videoProportion).toInt()
|
height = (screenWidth.toFloat() / videoProportion).toInt()
|
||||||
|
@ -470,7 +492,7 @@ class VideoFragment : ViewPagerFragment(), SurfaceHolder.Callback, SeekBar.OnSee
|
||||||
width = (videoProportion * screenHeight.toFloat()).toInt()
|
width = (videoProportion * screenHeight.toFloat()).toInt()
|
||||||
height = screenHeight
|
height = screenHeight
|
||||||
}
|
}
|
||||||
mSurfaceView!!.layoutParams = this
|
mTextureView!!.layoutParams = this
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -496,15 +518,15 @@ class VideoFragment : ViewPagerFragment(), SurfaceHolder.Callback, SeekBar.OnSee
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun skip(forward: Boolean) {
|
private fun skip(forward: Boolean) {
|
||||||
if (mMediaPlayer == null) {
|
if (mExoPlayer == null) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val curr = mMediaPlayer!!.currentPosition
|
val curr = mExoPlayer!!.currentPosition
|
||||||
val twoPercents = Math.max(mMediaPlayer!!.duration / 50, MIN_SKIP_LENGTH)
|
val twoPercents = Math.max((mExoPlayer!!.duration / 50).toInt(), MIN_SKIP_LENGTH)
|
||||||
val newProgress = if (forward) curr + twoPercents else curr - twoPercents
|
val newProgress = if (forward) curr + twoPercents else curr - twoPercents
|
||||||
val roundProgress = Math.round(newProgress / 1000f)
|
val roundProgress = Math.round(newProgress / 1000f)
|
||||||
val limitedProgress = Math.max(Math.min(mMediaPlayer!!.duration / 1000, roundProgress), 0)
|
val limitedProgress = Math.max(Math.min(mExoPlayer!!.duration.toInt(), roundProgress), 0)
|
||||||
setProgress(limitedProgress)
|
setProgress(limitedProgress)
|
||||||
if (!mIsPlaying) {
|
if (!mIsPlaying) {
|
||||||
togglePlayPause()
|
togglePlayPause()
|
||||||
|
@ -512,17 +534,16 @@ class VideoFragment : ViewPagerFragment(), SurfaceHolder.Callback, SeekBar.OnSee
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
|
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
|
||||||
if (mMediaPlayer != null && fromUser) {
|
if (mExoPlayer != null && fromUser) {
|
||||||
setProgress(progress)
|
setProgress(progress)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onStartTrackingTouch(seekBar: SeekBar) {
|
override fun onStartTrackingTouch(seekBar: SeekBar) {
|
||||||
initMediaPlayer()
|
if (mExoPlayer == null)
|
||||||
if (mMediaPlayer == null)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
mMediaPlayer!!.pause()
|
mExoPlayer!!.playWhenReady = false
|
||||||
mIsDragged = true
|
mIsDragged = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -530,7 +551,7 @@ class VideoFragment : ViewPagerFragment(), SurfaceHolder.Callback, SeekBar.OnSee
|
||||||
if (!mIsPlaying) {
|
if (!mIsPlaying) {
|
||||||
togglePlayPause()
|
togglePlayPause()
|
||||||
} else {
|
} else {
|
||||||
mMediaPlayer?.start()
|
mExoPlayer!!.playWhenReady = true
|
||||||
}
|
}
|
||||||
|
|
||||||
mIsDragged = false
|
mIsDragged = false
|
||||||
|
@ -549,7 +570,7 @@ class VideoFragment : ViewPagerFragment(), SurfaceHolder.Callback, SeekBar.OnSee
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mView!!.video_play_outline.animate().alpha(if (isFullscreen) 0f else 1f).start()
|
mView!!.video_play_outline.animate().alpha(if (isFullscreen) 0f else PLAY_PAUSE_VISIBLE_ALPHA).start()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getExtendedDetailsY(height: Int): Float {
|
private fun getExtendedDetailsY(height: Int): Float {
|
||||||
|
|
|
@ -6,12 +6,11 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
<SurfaceView
|
<TextureView
|
||||||
android:id="@+id/video_surface"
|
android:id="@+id/video_surface"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_centerInParent="true"
|
android:layout_centerInParent="true"/>
|
||||||
android:background="@android:color/transparent"/>
|
|
||||||
|
|
||||||
<com.simplemobiletools.gallery.helpers.MediaSideScroll
|
<com.simplemobiletools.gallery.helpers.MediaSideScroll
|
||||||
android:id="@+id/video_volume_controller"
|
android:id="@+id/video_volume_controller"
|
||||||
|
|
Loading…
Reference in a new issue