-
Notifications
You must be signed in to change notification settings - Fork 90
Expand file tree
/
Copy pathCommon.kt
More file actions
267 lines (250 loc) · 9.85 KB
/
Common.kt
File metadata and controls
267 lines (250 loc) · 9.85 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
package com.simform.videooperations
import android.content.ContentResolver
import android.content.Context
import android.content.Intent
import android.media.MediaExtractor
import android.media.MediaFormat
import android.media.MediaMetadataRetriever
import android.net.Uri
import android.os.Build
import android.os.Environment
import android.provider.OpenableColumns
import android.text.TextUtils
import androidx.appcompat.app.AppCompatActivity
import com.jaiselrahman.filepicker.activity.FilePickerActivity
import com.jaiselrahman.filepicker.config.Configurations
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
import java.io.IOException
import java.text.DecimalFormat
import java.util.Formatter
import java.util.Locale
/**
* Created by Ashvin Vavaliya on 24,November,2020
* Simform Solutions Pvt Ltd.
*/
object Common {
const val PERM = 111
const val VIDEO_FILE_REQUEST_CODE = 112
const val IMAGE_FILE_REQUEST_CODE = 113
const val AUDIO_FILE_REQUEST_CODE = 114
const val TIME_FORMAT = "HH:mm:ss"
const val OUT_PUT_DIR: String = "Output"
private val format: DecimalFormat = DecimalFormat("#.##")
private const val MB = (1024 * 1024).toLong()
private const val KB: Long = 1024
//Output Files
const val IMAGE: String = "IMAGE"
const val VIDEO: String = "VIDEO"
const val GIF: String = "GIF"
const val MP3: String = "MP3"
// Standard Ratio
const val RATIO_1: String = "16:9"
const val RATIO_2: String = "4:3"
const val RATIO_3: String = "16:10"
const val RATIO_4: String = "5:4"
const val RATIO_5: String = "2:21:1"
const val RATIO_6: String = "2:35:1"
const val RATIO_7: String = "2:39:1"
// Standard Bitrate
const val BITRATE_96: String = "96" //kbps
const val BITRATE_112: String = "112" //kbps
const val BITRATE_128: String = "128" //kbps
const val BITRATE_160: String = "160" //kbps
const val BITRATE_192: String = "192" //kbps
const val BITRATE_256: String = "256" //kbps
const val BITRATE_320: String = "320" //kbps
const val DURATION_LONGEST: String = "longest"
const val DURATION_SHORTEST: String = "shortest"
const val DURATION_FIRST: String = "first"
fun stringForTime(timeMs: Long?): String {
val mFormatBuilder = StringBuilder()
val mFormatter = Formatter(mFormatBuilder, Locale.getDefault())
val totalSeconds = timeMs?.div(1000)
val seconds = (totalSeconds?.rem(60))?.toInt()
val minutes = ((totalSeconds?.div(60))?.rem(60))?.toInt()
val hours = (totalSeconds?.div(3600))?.toInt()
mFormatBuilder.setLength(0)
return mFormatter.format("%02d:%02d:%02d", hours, minutes, seconds).toString()
}
fun getFrameRate(fileString: String) {
val extractor = MediaExtractor()
val file = File(fileString)
var fis: FileInputStream? = null
try {
fis = FileInputStream(file)
val fd = fis.fd
extractor.setDataSource(fd)
val numTracks = extractor.trackCount
for (i in 0 until numTracks) {
val format = extractor.getTrackFormat(i)
val mime = format.getString(MediaFormat.KEY_MIME)
if (mime?.startsWith("video/") == true) {
if (format.containsKey(MediaFormat.KEY_FRAME_RATE)) {
FFmpegQueryExtension().FRAME_RATE = format.getInteger(MediaFormat.KEY_FRAME_RATE)
}
}
}
} catch (e: Exception) {
e.printStackTrace()
} finally {
extractor.release()
try {
fis?.close()
} catch (e: Exception) {
e.printStackTrace()
}
}
}
fun getFileSize(file: File): String {
require(file.isFile) { "Expected a file" }
val length = file.length().toDouble()
if (length > MB) {
return format.format(length / MB).toString() + " MB"
}
return if (length > KB) {
format.format(length / KB).toString() + " KB"
} else {
format.format(length).toString() + " GB"
}
}
fun selectFile(activity: AppCompatActivity, maxSelection: Int, isImageSelection: Boolean, isAudioSelection: Boolean) {
val intent = Intent(activity, FilePickerActivity::class.java)
when {
isImageSelection -> {
intent.putExtra(
FilePickerActivity.CONFIGS, Configurations.Builder()
.setCheckPermission(true)
.setShowImages(true)
.setShowVideos(false)
.enableImageCapture(true)
.enableVideoCapture(false)
.setMaxSelection(maxSelection)
.setSkipZeroSizeFiles(true)
.build()
)
activity.startActivityForResult(intent, IMAGE_FILE_REQUEST_CODE)
}
isAudioSelection -> {
intent.putExtra(
FilePickerActivity.CONFIGS, Configurations.Builder()
.setCheckPermission(true)
.setShowImages(false)
.setShowVideos(false)
.setShowAudios(true)
.enableImageCapture(false)
.enableVideoCapture(false)
.setMaxSelection(maxSelection)
.setSkipZeroSizeFiles(true)
.build()
)
activity.startActivityForResult(intent, AUDIO_FILE_REQUEST_CODE)
}
else -> {
intent.putExtra(
FilePickerActivity.CONFIGS, Configurations.Builder()
.setCheckPermission(true)
.setShowImages(false)
.setShowVideos(true)
.enableImageCapture(false)
.enableVideoCapture(true)
.setMaxSelection(maxSelection)
.setSkipZeroSizeFiles(true)
.build()
)
activity.startActivityForResult(intent, VIDEO_FILE_REQUEST_CODE)
}
}
}
fun getFilePath(context: Context, fileExtension: String) : String {
val dir = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
when {
TextUtils.equals(fileExtension, VIDEO) -> Environment.DIRECTORY_MOVIES
TextUtils.equals(fileExtension, IMAGE) || TextUtils.equals(fileExtension, GIF) -> Environment.DIRECTORY_PICTURES
TextUtils.equals(fileExtension, MP3) -> Environment.DIRECTORY_MUSIC
else -> Environment.DIRECTORY_DOWNLOADS
}.let {
File(Environment.getExternalStoragePublicDirectory(it).toString())
}
} else {
// Fallback to app's private external files dir on older Android versions
File(context.getExternalFilesDir(Common.OUT_PUT_DIR).toString())
}
if (!dir.exists()) {
dir.mkdirs()
}
var extension:String? = null
when {
TextUtils.equals(fileExtension, IMAGE) -> {
extension = "%03d.jpg"
}
TextUtils.equals(fileExtension, VIDEO) -> {
extension = ".mp4"
}
TextUtils.equals(fileExtension, GIF) -> {
extension = ".gif"
}
TextUtils.equals(fileExtension, MP3) -> {
extension = ".mp3"
}
}
val dest = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
File(dir, System.currentTimeMillis().div(1000L).toString() + extension)
} else {
// Fallback for devices below Android 14
File(dir.path + File.separator + OUT_PUT_DIR + System.currentTimeMillis().div(1000L) + extension)
}
return dest.absolutePath
}
@Throws(IOException::class)
fun getFileFromAssets(context: Context, fileName: String): File =
File(context.cacheDir, fileName).also {
if (!it.exists()) {
it.outputStream().use { cache ->
context.assets.open(fileName).use { inputStream ->
inputStream.copyTo(cache)
}
}
}
}
fun saveFileToTempAndGetPath(context: Context, uri: Uri): String? {
val contentResolver = context.contentResolver
val fileName = getFileNameFromUri(contentResolver, uri)
val tempFile = File(context.cacheDir, fileName)
return try {
contentResolver.openInputStream(uri)?.use { inputStream ->
FileOutputStream(tempFile).use { outputStream ->
inputStream.copyTo(outputStream)
}
}
tempFile.absolutePath
} catch (e: Exception) {
e.printStackTrace()
null
}
}
private fun getFileNameFromUri(contentResolver: ContentResolver, uri: Uri): String {
var name = "temp_file"
val returnCursor = contentResolver.query(uri, null, null, null, null)
returnCursor?.use {
val nameIndex = it.getColumnIndex(OpenableColumns.DISPLAY_NAME)
if (it.moveToFirst() && nameIndex >= 0) {
name = it.getString(nameIndex)
}
}
return name
}
fun getDurationFromFile(file: File): Long {
val retriever = MediaMetadataRetriever()
return try {
retriever.setDataSource(file.absolutePath)
retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)?.toLong() ?: 0L
} catch (e: Exception) {
e.printStackTrace()
0L
} finally {
retriever.release()
}
}
}