fix #1097, optimize video thumbnail duration showing performance
This commit is contained in:
parent
2764f205ee
commit
8c97d7952a
11 changed files with 46 additions and 34 deletions
|
@ -801,7 +801,7 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val curMedia = mediaFetcher.getFilesFrom(directory.path, getImagesOnly, getVideosOnly, getProperDateTaken, favoritePaths)
|
val curMedia = mediaFetcher.getFilesFrom(directory.path, getImagesOnly, getVideosOnly, getProperDateTaken, favoritePaths, false)
|
||||||
val newDir = if (curMedia.isEmpty()) {
|
val newDir = if (curMedia.isEmpty()) {
|
||||||
if (directory.path != tempFolderPath) {
|
if (directory.path != tempFolderPath) {
|
||||||
dirPathsToRemove.add(directory.path)
|
dirPathsToRemove.add(directory.path)
|
||||||
|
@ -874,7 +874,7 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val newMedia = mediaFetcher.getFilesFrom(folder, getImagesOnly, getVideosOnly, getProperDateTaken, favoritePaths)
|
val newMedia = mediaFetcher.getFilesFrom(folder, getImagesOnly, getVideosOnly, getProperDateTaken, favoritePaths, false)
|
||||||
if (newMedia.isEmpty()) {
|
if (newMedia.isEmpty()) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,7 +111,7 @@ open class PhotoVideoActivity : SimpleActivity(), ViewPagerFragment.FragmentList
|
||||||
}
|
}
|
||||||
|
|
||||||
mIsVideo = type == TYPE_VIDEOS
|
mIsVideo = type == TYPE_VIDEOS
|
||||||
mMedium = Medium(null, filename, mUri.toString(), mUri!!.path.getParentPath(), 0, 0, file.length(), type, false, 0L)
|
mMedium = Medium(null, filename, mUri.toString(), mUri!!.path.getParentPath(), 0, 0, file.length(), type, 0, false, 0L)
|
||||||
supportActionBar?.title = mMedium!!.name
|
supportActionBar?.title = mMedium!!.name
|
||||||
bundle.putSerializable(MEDIUM, mMedium)
|
bundle.putSerializable(MEDIUM, mMedium)
|
||||||
|
|
||||||
|
|
|
@ -460,7 +460,7 @@ class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList<Thumbnai
|
||||||
|
|
||||||
val showVideoDuration = medium.isVideo() && config.showThumbnailVideoDuration
|
val showVideoDuration = medium.isVideo() && config.showThumbnailVideoDuration
|
||||||
if (showVideoDuration) {
|
if (showVideoDuration) {
|
||||||
video_duration.text = medium.getVideoDuration().getFormattedDuration()
|
video_duration.text = medium.videoDuration.getFormattedDuration()
|
||||||
video_duration.setTextColor(textColor)
|
video_duration.setTextColor(textColor)
|
||||||
}
|
}
|
||||||
video_duration.beVisibleIf(showVideoDuration)
|
video_duration.beVisibleIf(showVideoDuration)
|
||||||
|
|
|
@ -22,18 +22,19 @@ class GetMediaAsynctask(val context: Context, val mPath: String, val isPickImage
|
||||||
val pathToUse = if (showAll) SHOW_ALL else mPath
|
val pathToUse = if (showAll) SHOW_ALL else mPath
|
||||||
val getProperDateTaken = context.config.getFileSorting(pathToUse) and SORT_BY_DATE_TAKEN != 0
|
val getProperDateTaken = context.config.getFileSorting(pathToUse) and SORT_BY_DATE_TAKEN != 0
|
||||||
val favoritePaths = context.getFavoritePaths()
|
val favoritePaths = context.getFavoritePaths()
|
||||||
|
val getVideoDurations = context.config.showThumbnailVideoDuration
|
||||||
val media = if (showAll) {
|
val media = if (showAll) {
|
||||||
val foldersToScan = mediaFetcher.getFoldersToScan().filter { it != RECYCLE_BIN && it != FAVORITES }
|
val foldersToScan = mediaFetcher.getFoldersToScan().filter { it != RECYCLE_BIN && it != FAVORITES }
|
||||||
val media = ArrayList<Medium>()
|
val media = ArrayList<Medium>()
|
||||||
foldersToScan.forEach {
|
foldersToScan.forEach {
|
||||||
val newMedia = mediaFetcher.getFilesFrom(it, isPickImage, isPickVideo, getProperDateTaken, favoritePaths)
|
val newMedia = mediaFetcher.getFilesFrom(it, isPickImage, isPickVideo, getProperDateTaken, favoritePaths, getVideoDurations)
|
||||||
media.addAll(newMedia)
|
media.addAll(newMedia)
|
||||||
}
|
}
|
||||||
|
|
||||||
mediaFetcher.sortMedia(media, context.config.getFileSorting(SHOW_ALL))
|
mediaFetcher.sortMedia(media, context.config.getFileSorting(SHOW_ALL))
|
||||||
media
|
media
|
||||||
} else {
|
} else {
|
||||||
mediaFetcher.getFilesFrom(mPath, isPickImage, isPickVideo, getProperDateTaken, favoritePaths)
|
mediaFetcher.getFilesFrom(mPath, isPickImage, isPickVideo, getProperDateTaken, favoritePaths, getVideoDurations)
|
||||||
}
|
}
|
||||||
return mediaFetcher.groupMedia(media, pathToUse)
|
return mediaFetcher.groupMedia(media, pathToUse)
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,12 +4,14 @@ import android.content.Context
|
||||||
import androidx.room.Database
|
import androidx.room.Database
|
||||||
import androidx.room.Room
|
import androidx.room.Room
|
||||||
import androidx.room.RoomDatabase
|
import androidx.room.RoomDatabase
|
||||||
|
import androidx.room.migration.Migration
|
||||||
|
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||||
import com.simplemobiletools.gallery.pro.interfaces.DirectoryDao
|
import com.simplemobiletools.gallery.pro.interfaces.DirectoryDao
|
||||||
import com.simplemobiletools.gallery.pro.interfaces.MediumDao
|
import com.simplemobiletools.gallery.pro.interfaces.MediumDao
|
||||||
import com.simplemobiletools.gallery.pro.models.Directory
|
import com.simplemobiletools.gallery.pro.models.Directory
|
||||||
import com.simplemobiletools.gallery.pro.models.Medium
|
import com.simplemobiletools.gallery.pro.models.Medium
|
||||||
|
|
||||||
@Database(entities = [Directory::class, Medium::class], version = 4)
|
@Database(entities = [Directory::class, Medium::class], version = 5)
|
||||||
abstract class GalleryDatabase : RoomDatabase() {
|
abstract class GalleryDatabase : RoomDatabase() {
|
||||||
|
|
||||||
abstract fun DirectoryDao(): DirectoryDao
|
abstract fun DirectoryDao(): DirectoryDao
|
||||||
|
@ -24,7 +26,7 @@ abstract class GalleryDatabase : RoomDatabase() {
|
||||||
synchronized(GalleryDatabase::class) {
|
synchronized(GalleryDatabase::class) {
|
||||||
if (db == null) {
|
if (db == null) {
|
||||||
db = Room.databaseBuilder(context.applicationContext, GalleryDatabase::class.java, "gallery.db")
|
db = Room.databaseBuilder(context.applicationContext, GalleryDatabase::class.java, "gallery.db")
|
||||||
.fallbackToDestructiveMigration()
|
.addMigrations(MIGRATION_4_5)
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,5 +37,11 @@ abstract class GalleryDatabase : RoomDatabase() {
|
||||||
fun destroyInstance() {
|
fun destroyInstance() {
|
||||||
db = null
|
db = null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val MIGRATION_4_5 = object : Migration(4, 5) {
|
||||||
|
override fun migrate(database: SupportSQLiteDatabase) {
|
||||||
|
database.execSQL("ALTER TABLE media ADD COLUMN video_duration INTEGER default 0 NOT NULL")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package com.simplemobiletools.gallery.pro.extensions
|
package com.simplemobiletools.gallery.pro.extensions
|
||||||
|
|
||||||
|
import android.media.MediaMetadataRetriever
|
||||||
import com.bumptech.glide.signature.ObjectKey
|
import com.bumptech.glide.signature.ObjectKey
|
||||||
import com.simplemobiletools.commons.helpers.OTG_PATH
|
import com.simplemobiletools.commons.helpers.OTG_PATH
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
@ -43,3 +44,14 @@ fun String.getDistinctPath(): String {
|
||||||
toLowerCase()
|
toLowerCase()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun String.getVideoDuration(): Int {
|
||||||
|
var seconds = 0
|
||||||
|
try {
|
||||||
|
val retriever = MediaMetadataRetriever()
|
||||||
|
retriever.setDataSource(this)
|
||||||
|
seconds = Math.round(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION).toInt() / 1000f)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
}
|
||||||
|
return seconds
|
||||||
|
}
|
||||||
|
|
|
@ -523,7 +523,7 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupVideoDuration() {
|
private fun setupVideoDuration() {
|
||||||
mDuration = medium.getVideoDuration()
|
mDuration = medium.path.getVideoDuration()
|
||||||
setupTimeHolder()
|
setupTimeHolder()
|
||||||
setPosition(0)
|
setPosition(0)
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,8 @@ import java.util.*
|
||||||
class MediaFetcher(val context: Context) {
|
class MediaFetcher(val context: Context) {
|
||||||
var shouldStop = false
|
var shouldStop = false
|
||||||
|
|
||||||
fun getFilesFrom(curPath: String, isPickImage: Boolean, isPickVideo: Boolean, getProperDateTaken: Boolean, favoritePaths: ArrayList<String>): ArrayList<Medium> {
|
fun getFilesFrom(curPath: String, isPickImage: Boolean, isPickVideo: Boolean, getProperDateTaken: Boolean, favoritePaths: ArrayList<String>,
|
||||||
|
getVideoDurations: Boolean): ArrayList<Medium> {
|
||||||
val filterMedia = context.config.filterMedia
|
val filterMedia = context.config.filterMedia
|
||||||
if (filterMedia == 0) {
|
if (filterMedia == 0) {
|
||||||
return ArrayList()
|
return ArrayList()
|
||||||
|
@ -26,10 +27,10 @@ class MediaFetcher(val context: Context) {
|
||||||
|
|
||||||
val curMedia = ArrayList<Medium>()
|
val curMedia = ArrayList<Medium>()
|
||||||
if (curPath.startsWith(OTG_PATH)) {
|
if (curPath.startsWith(OTG_PATH)) {
|
||||||
val newMedia = getMediaOnOTG(curPath, isPickImage, isPickVideo, filterMedia, favoritePaths)
|
val newMedia = getMediaOnOTG(curPath, isPickImage, isPickVideo, filterMedia, favoritePaths, getVideoDurations)
|
||||||
curMedia.addAll(newMedia)
|
curMedia.addAll(newMedia)
|
||||||
} else {
|
} else {
|
||||||
val newMedia = getMediaInFolder(curPath, isPickImage, isPickVideo, filterMedia, getProperDateTaken, favoritePaths)
|
val newMedia = getMediaInFolder(curPath, isPickImage, isPickVideo, filterMedia, getProperDateTaken, favoritePaths, getVideoDurations)
|
||||||
curMedia.addAll(newMedia)
|
curMedia.addAll(newMedia)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,7 +168,7 @@ class MediaFetcher(val context: Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getMediaInFolder(folder: String, isPickImage: Boolean, isPickVideo: Boolean, filterMedia: Int, getProperDateTaken: Boolean,
|
private fun getMediaInFolder(folder: String, isPickImage: Boolean, isPickVideo: Boolean, filterMedia: Int, getProperDateTaken: Boolean,
|
||||||
favoritePaths: ArrayList<String>): ArrayList<Medium> {
|
favoritePaths: ArrayList<String>, getVideoDurations: Boolean): ArrayList<Medium> {
|
||||||
val media = ArrayList<Medium>()
|
val media = ArrayList<Medium>()
|
||||||
|
|
||||||
val deletedMedia = if (folder == RECYCLE_BIN) {
|
val deletedMedia = if (folder == RECYCLE_BIN) {
|
||||||
|
@ -231,6 +232,7 @@ class MediaFetcher(val context: Context) {
|
||||||
} else {
|
} else {
|
||||||
val lastModified = file.lastModified()
|
val lastModified = file.lastModified()
|
||||||
var dateTaken = lastModified
|
var dateTaken = lastModified
|
||||||
|
val videoDuration = if (getVideoDurations) path.getVideoDuration() else 0
|
||||||
|
|
||||||
if (getProperDateTaken) {
|
if (getProperDateTaken) {
|
||||||
dateTaken = dateTakens.remove(filename) ?: lastModified
|
dateTaken = dateTakens.remove(filename) ?: lastModified
|
||||||
|
@ -245,14 +247,15 @@ class MediaFetcher(val context: Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
val isFavorite = favoritePaths.contains(path)
|
val isFavorite = favoritePaths.contains(path)
|
||||||
val medium = Medium(null, filename, path, file.parent, lastModified, dateTaken, size, type, isFavorite, 0L)
|
val medium = Medium(null, filename, path, file.parent, lastModified, dateTaken, size, type, videoDuration, isFavorite, 0L)
|
||||||
media.add(medium)
|
media.add(medium)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return media
|
return media
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getMediaOnOTG(folder: String, isPickImage: Boolean, isPickVideo: Boolean, filterMedia: Int, favoritePaths: ArrayList<String>): ArrayList<Medium> {
|
private fun getMediaOnOTG(folder: String, isPickImage: Boolean, isPickVideo: Boolean, filterMedia: Int, favoritePaths: ArrayList<String>,
|
||||||
|
getVideoDurations: Boolean): ArrayList<Medium> {
|
||||||
val media = ArrayList<Medium>()
|
val media = ArrayList<Medium>()
|
||||||
val files = context.getDocumentFile(folder)?.listFiles() ?: return media
|
val files = context.getDocumentFile(folder)?.listFiles() ?: return media
|
||||||
val doExtraCheck = context.config.doExtraCheck
|
val doExtraCheck = context.config.doExtraCheck
|
||||||
|
@ -307,8 +310,9 @@ class MediaFetcher(val context: Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
val path = Uri.decode(file.uri.toString().replaceFirst("${context.config.OTGTreeUri}/document/${context.config.OTGPartition}%3A", OTG_PATH))
|
val path = Uri.decode(file.uri.toString().replaceFirst("${context.config.OTGTreeUri}/document/${context.config.OTGPartition}%3A", OTG_PATH))
|
||||||
|
val videoDuration = if (getVideoDurations) path.getVideoDuration() else 0
|
||||||
val isFavorite = favoritePaths.contains(path)
|
val isFavorite = favoritePaths.contains(path)
|
||||||
val medium = Medium(null, filename, path, folder, dateModified, dateTaken, size, type, isFavorite, 0L)
|
val medium = Medium(null, filename, path, folder, dateModified, dateTaken, size, type, videoDuration, isFavorite, 0L)
|
||||||
media.add(medium)
|
media.add(medium)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,16 +9,16 @@ import com.simplemobiletools.gallery.pro.models.Medium
|
||||||
|
|
||||||
@Dao
|
@Dao
|
||||||
interface MediumDao {
|
interface MediumDao {
|
||||||
@Query("SELECT filename, full_path, parent_path, last_modified, date_taken, size, type, is_favorite, deleted_ts FROM media WHERE deleted_ts = 0 AND parent_path = :path COLLATE NOCASE")
|
@Query("SELECT filename, full_path, parent_path, last_modified, date_taken, size, type, video_duration, is_favorite, deleted_ts FROM media WHERE deleted_ts = 0 AND parent_path = :path COLLATE NOCASE")
|
||||||
fun getMediaFromPath(path: String): List<Medium>
|
fun getMediaFromPath(path: String): List<Medium>
|
||||||
|
|
||||||
@Query("SELECT filename, full_path, parent_path, last_modified, date_taken, size, type, is_favorite, deleted_ts FROM media WHERE deleted_ts = 0 AND is_favorite = 1")
|
@Query("SELECT filename, full_path, parent_path, last_modified, date_taken, size, type, video_duration, is_favorite, deleted_ts FROM media WHERE deleted_ts = 0 AND is_favorite = 1")
|
||||||
fun getFavorites(): List<Medium>
|
fun getFavorites(): List<Medium>
|
||||||
|
|
||||||
@Query("SELECT full_path FROM media WHERE deleted_ts = 0 AND is_favorite = 1")
|
@Query("SELECT full_path FROM media WHERE deleted_ts = 0 AND is_favorite = 1")
|
||||||
fun getFavoritePaths(): List<String>
|
fun getFavoritePaths(): List<String>
|
||||||
|
|
||||||
@Query("SELECT filename, full_path, parent_path, last_modified, date_taken, size, type, is_favorite, deleted_ts FROM media WHERE deleted_ts != 0")
|
@Query("SELECT filename, full_path, parent_path, last_modified, date_taken, size, type, video_duration, is_favorite, deleted_ts FROM media WHERE deleted_ts != 0")
|
||||||
fun getDeletedMedia(): List<Medium>
|
fun getDeletedMedia(): List<Medium>
|
||||||
|
|
||||||
@Insert(onConflict = REPLACE)
|
@Insert(onConflict = REPLACE)
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package com.simplemobiletools.gallery.pro.models
|
package com.simplemobiletools.gallery.pro.models
|
||||||
|
|
||||||
import android.media.MediaMetadataRetriever
|
|
||||||
import androidx.room.ColumnInfo
|
import androidx.room.ColumnInfo
|
||||||
import androidx.room.Entity
|
import androidx.room.Entity
|
||||||
import androidx.room.Index
|
import androidx.room.Index
|
||||||
|
@ -26,6 +25,7 @@ data class Medium(
|
||||||
@ColumnInfo(name = "date_taken") var taken: Long,
|
@ColumnInfo(name = "date_taken") var taken: Long,
|
||||||
@ColumnInfo(name = "size") val size: Long,
|
@ColumnInfo(name = "size") val size: Long,
|
||||||
@ColumnInfo(name = "type") val type: Int,
|
@ColumnInfo(name = "type") val type: Int,
|
||||||
|
@ColumnInfo(name = "video_duration") val videoDuration: Int,
|
||||||
@ColumnInfo(name = "is_favorite") var isFavorite: Boolean,
|
@ColumnInfo(name = "is_favorite") var isFavorite: Boolean,
|
||||||
@ColumnInfo(name = "deleted_ts") var deletedTS: Long) : Serializable, ThumbnailItem() {
|
@ColumnInfo(name = "deleted_ts") var deletedTS: Long) : Serializable, ThumbnailItem() {
|
||||||
|
|
||||||
|
@ -77,17 +77,4 @@ data class Medium(
|
||||||
|
|
||||||
return calendar.timeInMillis.toString()
|
return calendar.timeInMillis.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getVideoDuration(): Int {
|
|
||||||
var seconds = 0
|
|
||||||
try {
|
|
||||||
if (isVideo()) {
|
|
||||||
val retriever = MediaMetadataRetriever()
|
|
||||||
retriever.setDataSource(path)
|
|
||||||
seconds = Math.round(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION).toInt() / 1000f)
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
|
||||||
}
|
|
||||||
return seconds
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ class RefreshMediaReceiver : BroadcastReceiver() {
|
||||||
|
|
||||||
Thread {
|
Thread {
|
||||||
val medium = Medium(null, path.getFilenameFromPath(), path, path.getParentPath(), System.currentTimeMillis(), System.currentTimeMillis(),
|
val medium = Medium(null, path.getFilenameFromPath(), path, path.getParentPath(), System.currentTimeMillis(), System.currentTimeMillis(),
|
||||||
File(path).length(), getFileType(path), false, 0L)
|
File(path).length(), getFileType(path), 0, false, 0L)
|
||||||
context.galleryDB.MediumDao().insert(medium)
|
context.galleryDB.MediumDao().insert(medium)
|
||||||
}.start()
|
}.start()
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue