Skip to content

Commit 49ce06a

Browse files
authored
Merge pull request #215 from xyoye/dev_4.1.0
Dev 4.1.0
2 parents 8597829 + 0b4b7cc commit 49ce06a

File tree

15 files changed

+415
-80
lines changed

15 files changed

+415
-80
lines changed

common_component/src/main/java/com/xyoye/common_component/config/AppConfigTable.kt

+5
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package com.xyoye.common_component.config
22

33
import androidx.appcompat.app.AppCompatDelegate
44
import com.xyoye.common_component.network.config.Api
5+
import com.xyoye.common_component.utils.meida.VideoExtension
56
import com.xyoye.data_component.enums.HistorySort
67
import com.xyoye.data_component.enums.StorageSort
78
import com.xyoye.mmkv_annotation.MMKVFiled
@@ -84,4 +85,8 @@ object AppConfigTable {
8485
@MMKVFiled
8586
//备用域名地址
8687
var backupDomain: String = Api.DAN_DAN_SPARE
88+
89+
@MMKVFiled
90+
//支持的视频后缀
91+
var supportVideoExtension: String = VideoExtension.supportText
8792
}

common_component/src/main/java/com/xyoye/common_component/storage/impl/VideoStorage.kt

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ import com.xyoye.common_component.resolver.MediaResolver
66
import com.xyoye.common_component.storage.AbstractStorage
77
import com.xyoye.common_component.storage.file.StorageFile
88
import com.xyoye.common_component.storage.file.impl.VideoStorageFile
9-
import com.xyoye.common_component.utils.MediaUtils
109
import com.xyoye.common_component.utils.getFileName
1110
import com.xyoye.common_component.utils.getFileNameNoExtension
1211
import com.xyoye.common_component.utils.isDanmuFile
1312
import com.xyoye.common_component.utils.isSubtitleFile
13+
import com.xyoye.common_component.utils.meida.VideoScan
1414
import com.xyoye.common_component.utils.subtitle.SubtitleFinder
1515
import com.xyoye.data_component.bean.FolderBean
1616
import com.xyoye.data_component.bean.LocalDanmuBean
@@ -126,7 +126,7 @@ class VideoStorage(library: MediaLibraryEntity) : AbstractStorage(library) {
126126
private suspend fun deepRefresh() {
127127
//系统视频数据 = 自定义扫描目录视频 + MediaStore中系统视频
128128
val systemVideos = DatabaseManager.instance.getExtendFolderDao().getAll()
129-
.flatMap { MediaUtils.scanVideoFile(it.folderPath) }
129+
.flatMap { VideoScan.traverse(it.folderPath) }
130130
.plus(MediaResolver.queryVideo())
131131
.distinctBy { it.filePath }
132132

common_component/src/main/java/com/xyoye/common_component/utils/MediaUtils.kt

+2-65
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,12 @@ import android.content.Context
66
import android.database.Cursor
77
import android.database.sqlite.SQLiteException
88
import android.graphics.Bitmap
9-
import android.media.MediaMetadataRetriever
109
import android.net.Uri
1110
import android.os.Build
1211
import android.provider.MediaStore
1312
import com.xyoye.common_component.base.app.BaseApplication
14-
import com.xyoye.common_component.extension.isInvalid
1513
import com.xyoye.common_component.extension.toText
16-
import com.xyoye.data_component.entity.VideoEntity
14+
import com.xyoye.common_component.utils.meida.VideoExtension
1715
import java.io.File
1816
import java.io.FileOutputStream
1917
import java.io.IOException
@@ -25,14 +23,6 @@ import java.util.Locale
2523
* Created by xyoye on 2020/11/26.
2624
*/
2725

28-
private val commonVideoExtension = arrayOf(
29-
"3gp", "avi", "flv", "mp4",
30-
"m4v", "mkv", "mov", "mpeg",
31-
"mpg", "mpe", "rm", "rmvb",
32-
"wmv", "asf", "asx", "dat",
33-
"vob", "m3u8", "m2ts", "m4s"
34-
)
35-
3626
val supportSubtitleExtension = arrayOf(
3727
"ass", "scc", "stl", "srt",
3828
"ttml"
@@ -45,7 +35,7 @@ val supportAudioExtension = arrayOf(
4535

4636
fun isVideoFile(filePath: String): Boolean {
4737
val extension = getFileExtension(filePath)
48-
return commonVideoExtension.contains(extension.lowercase(Locale.ROOT))
38+
return VideoExtension.isSupport(extension)
4939
}
5040

5141
fun isSubtitleFile(filePath: String): Boolean {
@@ -109,41 +99,6 @@ object MediaUtils {
10999
}
110100
}
111101

112-
/**
113-
* 扫描文件夹内视频文件
114-
*/
115-
fun scanVideoFile(folderPath: String): MutableList<VideoEntity> {
116-
val folderFile = File(folderPath)
117-
if (!folderFile.exists())
118-
return mutableListOf()
119-
120-
val childFileArray = folderFile.listFiles() ?: return mutableListOf()
121-
122-
val videoEntities = mutableListOf<VideoEntity>()
123-
childFileArray.forEach {
124-
if (it.isFile && isVideoFile(it.absolutePath)) {
125-
videoEntities.add(
126-
VideoEntity(
127-
0,
128-
0,
129-
0,
130-
it.absolutePath,
131-
folderPath,
132-
null,
133-
null,
134-
getVideoDuration(it),
135-
it.length(),
136-
isFilter = false,
137-
isExtend = true
138-
)
139-
)
140-
} else if (it.isDirectory) {
141-
videoEntities.addAll(scanVideoFile(it.absolutePath))
142-
}
143-
}
144-
return videoEntities
145-
}
146-
147102
/**
148103
* 获取Uri对应文件的真实路径
149104
*/
@@ -210,22 +165,4 @@ object MediaUtils {
210165
}
211166
return false
212167
}
213-
214-
private fun getVideoDuration(videoFile: File): Long {
215-
if (videoFile.isInvalid()) {
216-
return 0
217-
}
218-
val retriever = MediaMetadataRetriever()
219-
return try {
220-
retriever.setDataSource(BaseApplication.getAppContext(), Uri.fromFile(videoFile))
221-
retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)
222-
?.toLongOrNull()
223-
?: 0
224-
} catch (e: Exception) {
225-
e.printStackTrace()
226-
0
227-
} finally {
228-
retriever.release()
229-
}
230-
}
231168
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
package com.xyoye.common_component.utils.meida
2+
3+
import com.xyoye.common_component.config.AppConfig
4+
5+
/**
6+
* Created by xyoye on 2024/2/4
7+
*/
8+
9+
object VideoExtension {
10+
11+
// 视频文件扩展名分隔符
12+
private const val SEPARATOR = ","
13+
14+
// 默认支持的视频文件扩展名
15+
private val defaultSupport = arrayOf(
16+
"3gp", "asf", "asx", "avi",
17+
"dat", "flv", "m2ts", "m3u8",
18+
"m4s", "m4v", "mkv", "mov",
19+
"mp4", "mpe", "mpeg", "mpg",
20+
"rm", "rmvb", "vob", "wmv"
21+
)
22+
23+
// 当前支持的视频文件扩展名
24+
private val _support = defaultSupport.toMutableList()
25+
val support: List<String> get() = _support
26+
27+
// 当前支持的视频文件扩展名文本
28+
val supportText: String get() = _support.joinToString(SEPARATOR)
29+
30+
init {
31+
refresh()
32+
}
33+
34+
/**
35+
* 重置为默认支持的视频文件扩展名
36+
*/
37+
fun resetDefault() {
38+
AppConfig.putSupportVideoExtension(defaultSupport.joinToString(SEPARATOR))
39+
refresh()
40+
}
41+
42+
/**
43+
* 更新支持的视频文件扩展名
44+
*/
45+
fun update(extensionText: String): Boolean {
46+
return update(extensionText.split(SEPARATOR))
47+
}
48+
49+
/**
50+
* 更新支持的视频文件扩展名
51+
*/
52+
fun update(extensions: List<String>): Boolean {
53+
val storeExtensions = extensions.filter { it.isNotBlank() }.map { it.lowercase() }
54+
if (storeExtensions.isEmpty()) {
55+
return false
56+
}
57+
AppConfig.putSupportVideoExtension(storeExtensions.joinToString(SEPARATOR))
58+
refresh()
59+
return true
60+
}
61+
62+
/**
63+
* 是否是支持的视频文件扩展名
64+
*/
65+
fun isSupport(extension: String): Boolean {
66+
return _support.contains(extension.lowercase())
67+
}
68+
69+
/**
70+
* 从磁盘中获取支持的视频文件扩展名
71+
*/
72+
private fun refresh() {
73+
val stored = AppConfig.getSupportVideoExtension()?.split(SEPARATOR)
74+
if (stored.isNullOrEmpty()) {
75+
return
76+
}
77+
_support.clear()
78+
_support.addAll(stored)
79+
}
80+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
package com.xyoye.common_component.utils.meida
2+
3+
import android.media.MediaMetadataRetriever
4+
import android.net.Uri
5+
import com.xyoye.common_component.base.app.BaseApplication
6+
import com.xyoye.common_component.extension.isInvalid
7+
import com.xyoye.common_component.utils.isVideoFile
8+
import com.xyoye.data_component.entity.VideoEntity
9+
import java.io.File
10+
11+
/**
12+
* Created by xyoye on 2024/2/4
13+
*/
14+
15+
object VideoScan {
16+
17+
/**
18+
* 遍历路径内的视频文件
19+
*/
20+
fun traverse(filePath: String): List<VideoEntity> {
21+
return try {
22+
traverse(File(filePath))
23+
} catch (e: Exception) {
24+
e.printStackTrace()
25+
emptyList()
26+
}
27+
}
28+
29+
/**
30+
* 遍历文件内的视频文件,包括文件自身
31+
*/
32+
private fun traverse(file: File): List<VideoEntity> {
33+
if (file.isFile) {
34+
return if (file.isInvalid()) {
35+
return emptyList()
36+
} else if (isVideoFile(file.absolutePath)) {
37+
listOf(generateVideoEntity(file))
38+
} else {
39+
emptyList()
40+
}
41+
}
42+
43+
if (file.exists().not() || file.canRead().not()) {
44+
return emptyList()
45+
}
46+
return file.listFiles()
47+
?.flatMap { traverse(it) }
48+
?: emptyList()
49+
}
50+
51+
/**
52+
* 生成视频数据库实体
53+
*/
54+
private fun generateVideoEntity(file: File): VideoEntity {
55+
return VideoEntity(
56+
0,
57+
0,
58+
0,
59+
file.absolutePath,
60+
file.parentFile?.absolutePath.orEmpty(),
61+
null,
62+
null,
63+
getVideoDuration(file),
64+
file.length(),
65+
isFilter = false,
66+
isExtend = true
67+
)
68+
}
69+
70+
/**
71+
* 获取视频时长
72+
*/
73+
private fun getVideoDuration(videoFile: File): Long {
74+
if (videoFile.isInvalid()) {
75+
return 0
76+
}
77+
val retriever = MediaMetadataRetriever()
78+
return try {
79+
retriever.setDataSource(BaseApplication.getAppContext(), Uri.fromFile(videoFile))
80+
retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)
81+
?.toLongOrNull()
82+
?: 0
83+
} catch (e: Exception) {
84+
e.printStackTrace()
85+
0
86+
} finally {
87+
retriever.release()
88+
}
89+
}
90+
}

common_component/src/main/java/com/xyoye/common_component/weight/dialog/FileManagerDialog.kt

+4-1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ class FileManagerDialog(
4040
activity: Activity,
4141
private val action: FileManagerAction,
4242
private var defaultFolderPath: String? = null,
43+
private val dismissWhenClickPositive: Boolean = true,
4344
private val listener: (resultPath: String) -> Unit
4445
) : BaseBottomDialog<DialogFileManagerBinding>(activity) {
4546

@@ -79,9 +80,11 @@ class FileManagerDialog(
7980
setNegativeListener { dismiss() }
8081

8182
setPositiveListener {
82-
dismiss()
8383
AppConfig.putLastOpenFolder(currentDirPath)
8484
listener.invoke(currentDirPath)
85+
if (dismissWhenClickPositive) {
86+
dismiss()
87+
}
8588
}
8689

8790
binding.rootPathTv.setOnClickListener {

player_component/src/main/java/com/xyoye/player_component/ui/activities/player_intent/PlayerIntentViewModel.kt

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ import com.xyoye.common_component.source.VideoSourceManager
99
import com.xyoye.common_component.source.factory.StorageVideoSourceFactory
1010
import com.xyoye.common_component.storage.StorageFactory
1111
import com.xyoye.common_component.storage.impl.LinkStorage
12-
import com.xyoye.common_component.utils.MediaUtils
1312
import com.xyoye.common_component.utils.SupervisorScope
1413
import com.xyoye.common_component.utils.getDirPath
14+
import com.xyoye.common_component.utils.meida.VideoScan
1515
import com.xyoye.common_component.weight.ToastCenter
1616
import com.xyoye.data_component.entity.ExtendFolderEntity
1717
import com.xyoye.data_component.entity.MediaLibraryEntity
@@ -38,7 +38,7 @@ class PlayerIntentViewModel : BaseViewModel() {
3838
return@launch
3939

4040
val folderPath = getDirPath(filePath)
41-
val extendVideos = MediaUtils.scanVideoFile(folderPath)
41+
val extendVideos = VideoScan.traverse(folderPath)
4242
if (extendVideos.isNotEmpty()) {
4343
DatabaseManager.instance.getExtendFolderDao().insert(
4444
ExtendFolderEntity(folderPath, extendVideos.size)

0 commit comments

Comments
 (0)