Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions app/src/main/java/com/nextplayer/ThumbnailUtils.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.nextplayer

import android.graphics.Bitmap
import android.media.MediaMetadataRetriever
import androidx.collection.LruCache
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext

object ThumbnailUtils {
private val cache = LruCache<String, Bitmap>(50)

suspend fun getVideoThumbnailAsync(path: String): Bitmap? {
cache.get(path)?.let { return it }
return withContext(Dispatchers.IO) {
val retriever = MediaMetadataRetriever()
try {
retriever.setDataSource(path)
val bmp = retriever.frameAtTime
if (bmp != null) cache.put(path, bmp)
bmp
} catch (e: Exception) {
null
} finally {
retriever.release()
}
}
}
}
47 changes: 47 additions & 0 deletions app/src/main/java/com/nextplayer/ui/VideoListAdapter.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package com.nextplayer.ui

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.RecyclerView
import com.nextplayer.ThumbnailUtils
import com.nextplayer.model.Video
import com.nextplayer.R
import kotlinx.coroutines.launch

class VideoListAdapter(private val videos: List<Video>) : RecyclerView.Adapter<VideoListAdapter.ViewHolder>() {

class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val thumbnailImageView: ImageView = itemView.findViewById(R.id.thumbnailImageView)
val titleTextView: TextView = itemView.findViewById(R.id.titleTextView)
val durationTextView: TextView = itemView.findViewById(R.id.durationTextView)
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.video_list_item, parent, false)
return ViewHolder(view)
}

override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val video = videos[position]
holder.titleTextView.text = video.title
holder.durationTextView.text = video.duration

holder.thumbnailImageView.setImageResource(R.drawable.ic_video_placeholder)
val videoPath = video.path
val lifecycleOwner = holder.itemView.context as? LifecycleOwner
lifecycleOwner?.lifecycleScope?.launch {
val thumbnail = ThumbnailUtils.getVideoThumbnailAsync(videoPath)
if (thumbnail != null) {
holder.thumbnailImageView.setImageBitmap(thumbnail)
}
}
}

override fun getItemCount() = videos.size
}
18 changes: 18 additions & 0 deletions app/src/main/res/layout/item_video.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="8dp">

<ImageView
android:id="@+id/thumbnailImageView"
android:layout_width="60dp"
android:layout_height="60dp"
android:scaleType="centerCrop"
android:layout_marginEnd="8dp"
android:contentDescription="@string/video_thumbnail"/>

<!-- ...existing views for video title, duration, etc.... -->

</LinearLayout>