Added video player

This commit is contained in:
Sylvain Berfini 2023-11-16 17:10:24 +01:00
parent b6c146f123
commit 8d05d786ce
3 changed files with 120 additions and 40 deletions

View file

@ -6,6 +6,7 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.annotation.UiThread
import androidx.core.view.doOnPreDraw
import androidx.lifecycle.ViewModelProvider
import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs
@ -72,5 +73,44 @@ class FileViewerFragment : GenericFragment() {
binding.dotsIndicator.attachTo(binding.pdfViewPager)
}
}
viewModel.isVideo.observe(viewLifecycleOwner) { isVideo ->
if (isVideo) {
binding.videoPlayer.setVideoPath(path)
binding.videoPlayer.setOnCompletionListener {
Log.i("$TAG End of file reached")
viewModel.isVideoPlaying.value = false
}
(view.parent as? ViewGroup)?.doOnPreDraw {
binding.videoPlayer.start()
viewModel.isVideoPlaying.value = true
}
}
}
viewModel.toggleVideoPlayPauseEvent.observe(viewLifecycleOwner) {
it.consume { play ->
if (play) {
binding.videoPlayer.start()
} else {
binding.videoPlayer.pause()
}
}
}
}
override fun onPause() {
if (binding.videoPlayer.isPlaying) {
binding.videoPlayer.pause()
viewModel.isVideoPlaying.value = false
}
super.onPause()
}
override fun onDestroyView() {
binding.videoPlayer.stopPlayback()
super.onDestroyView()
}
}

View file

@ -3,6 +3,7 @@ package org.linphone.ui.main.viewer.viewmodel
import android.graphics.Bitmap
import android.graphics.pdf.PdfRenderer
import android.os.ParcelFileDescriptor
import android.webkit.MimeTypeMap
import android.widget.ImageView
import androidx.annotation.UiThread
import androidx.lifecycle.MutableLiveData
@ -29,10 +30,18 @@ class FileViewModel @UiThread constructor() : ViewModel() {
val isPdf = MutableLiveData<Boolean>()
val isVideo = MutableLiveData<Boolean>()
val isVideoPlaying = MutableLiveData<Boolean>()
val pdfRendererReadyEvent: MutableLiveData<Event<Boolean>> by lazy {
MutableLiveData<Event<Boolean>>()
}
val toggleVideoPlayPauseEvent: MutableLiveData<Event<Boolean>> by lazy {
MutableLiveData<Event<Boolean>>()
}
// Below are required for PDF viewer
private lateinit var pdfRenderer: PdfRenderer
@ -40,8 +49,11 @@ class FileViewModel @UiThread constructor() : ViewModel() {
var screenHeight: Int = 0
// End of PDF viewer required variables
init {
fullScreenMode.value = true
override fun onCleared() {
if (::pdfRenderer.isInitialized) {
pdfRenderer.close()
}
super.onCleared()
}
@UiThread
@ -50,34 +62,38 @@ class FileViewModel @UiThread constructor() : ViewModel() {
fileName.value = name
val extension = FileUtils.getExtensionFromFileName(name)
if (extension == "pdf") {
Log.i("$TAG File [$file] seems to be a PDF")
isPdf.value = true
fullScreenMode.value = false
val mime = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension)
when (FileUtils.getMimeType(mime)) {
FileUtils.MimeType.Pdf -> {
Log.i("$TAG File [$file] seems to be a PDF")
isPdf.value = true
fullScreenMode.value = false
viewModelScope.launch {
withContext(Dispatchers.IO) {
val input = ParcelFileDescriptor.open(
File(file),
ParcelFileDescriptor.MODE_READ_ONLY
)
pdfRenderer = PdfRenderer(input)
Log.i("$TAG ${pdfRenderer.pageCount} pages in file $file")
pdfRendererReadyEvent.postValue(Event(true))
viewModelScope.launch {
withContext(Dispatchers.IO) {
val input = ParcelFileDescriptor.open(
File(file),
ParcelFileDescriptor.MODE_READ_ONLY
)
pdfRenderer = PdfRenderer(input)
Log.i("$TAG ${pdfRenderer.pageCount} pages in file $file")
pdfRendererReadyEvent.postValue(Event(true))
}
}
}
} else {
path.value = file
FileUtils.MimeType.Video -> {
Log.i("$TAG File [$file] seems to be a video")
isVideo.value = true
isVideoPlaying.value = false
fullScreenMode.value = true
}
else -> {
path.value = file
fullScreenMode.value = true
}
}
}
override fun onCleared() {
if (::pdfRenderer.isInitialized) {
pdfRenderer.close()
}
super.onCleared()
}
@UiThread
fun toggleFullScreen() {
fullScreenMode.value = fullScreenMode.value != true
@ -115,4 +131,11 @@ class FileViewModel @UiThread constructor() : ViewModel() {
}
}
}
@UiThread
fun playPauseVideo() {
val playVideo = isVideoPlaying.value == false
isVideoPlaying.value = playVideo
toggleVideoPlayPauseEvent.value = Event(playVideo)
}
}

View file

@ -24,37 +24,43 @@
android:layout_height="match_parent"
android:background="@color/black">
<com.github.chrisbanes.photoview.PhotoView
android:id="@+id/image"
<VideoView
android:id="@+id/video_player"
android:onClick="@{() -> viewModel.toggleFullScreen()}"
android:layout_width="0dp"
android:layout_height="0dp"
android:src="@drawable/illu"
android:adjustViewBounds="true"
android:scaleType="fitCenter"
coilFile="@{viewModel.path}"
android:visibility="@{viewModel.isPdf ? View.GONE : View.VISIBLE}"
android:layout_height="wrap_content"
android:visibility="@{viewModel.isVideo ? View.VISIBLE : View.GONE}"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
app:layout_constraintEnd_toEndOf="parent"/>
<ImageView
android:id="@+id/play_pause_video_playback"
android:onClick="@{() -> viewModel.playPauseVideo()}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:padding="8dp"
android:src="@{viewModel.isVideoPlaying ? @drawable/pause_fill : @drawable/play_fill, default=@drawable/play_fill}"
android:visibility="@{viewModel.isVideo &amp;&amp; !viewModel.fullScreenMode ? View.VISIBLE : View.GONE, default=gone}"
app:layout_constraintBottom_toTopOf="@id/file_name"
app:layout_constraintStart_toStartOf="@id/pdf_view_pager"
app:layout_constraintEnd_toEndOf="@id/pdf_view_pager"
app:tint="@color/orange_main_500"/>
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/pdf_view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:visibility="@{viewModel.isPdf ? View.VISIBLE : View.GONE, default=gone}"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
android:visibility="@{viewModel.isPdf ? View.VISIBLE : View.GONE, default=gone}" />
<com.tbuonomo.viewpagerdotsindicator.DotsIndicator
android:id="@+id/dots_indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="20dp"
android:layout_marginBottom="10dp"
android:visibility="@{viewModel.isPdf ? View.VISIBLE : View.GONE, default=gone}"
app:dotsColor="@color/gray_main2_200"
app:dotsCornerRadius="8dp"
@ -67,6 +73,17 @@
app:layout_constraintStart_toStartOf="@id/pdf_view_pager"
app:layout_constraintEnd_toEndOf="@id/pdf_view_pager" />
<com.github.chrisbanes.photoview.PhotoView
android:id="@+id/image"
android:onClick="@{() -> viewModel.toggleFullScreen()}"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/illu"
android:adjustViewBounds="true"
android:scaleType="fitCenter"
coilFile="@{viewModel.path}"
android:visibility="@{viewModel.isPdf || viewModel.isVideo ? View.GONE : View.VISIBLE}" />
<ImageView
android:id="@+id/back"
android:onClick="@{backClickListener}"
@ -90,7 +107,7 @@
android:background="@color/white"
android:paddingStart="10dp"
android:paddingEnd="10dp"
android:text="Conversation"
android:text=""
android:visibility="@{viewModel.fullScreenMode ? View.GONE : View.VISIBLE}"
app:layout_constraintEnd_toStartOf="@id/share"
app:layout_constraintStart_toEndOf="@id/back"