I am newbie in Android. I have one requirement in my application. I need to download audio files, .mp3 files from server using Downloadmanager and save it in specific folder in my device. Please help me to complete this task
Thanks in advance
The Android DownloadManager introduced in Android 2.3. (API 9) is a system service which allows to handle long-running HTTP downloads in the background and notify the triggering application via a broadcast receiver once the download is finished.
Courtesy:
http://www.vogella.com/blog/2011/06/14/android-downloadmanager-example/
Please see the below code
object DownloadHelper {
private var downloadReference: Long = 0
private lateinit var downloadManager: DownloadManager
var completeListener:DownloadCompleteListener?= null
interface DownloadCompleteListener{
fun ondownloadComplete(name:String,path:String?,uri:Uri?)
fun ondownloadFailled(error:String)
}
private val receiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val action = intent.action
if (action == DownloadManager.ACTION_DOWNLOAD_COMPLETE) {
val downloadId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1)
if (downloadId != downloadReference) {
context.unregisterReceiver(this)
return
}
val query = DownloadManager.Query()
query.setFilterById(downloadReference)
val cursor = downloadManager.query(query)
if(cursor != null){
cursor?.let {
if (cursor.moveToFirst()) {
val columnIndex = cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)
if (DownloadManager.STATUS_SUCCESSFUL == cursor.getInt(columnIndex)) {
var localFile = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI))
var localName = localFile.substring(localFile.lastIndexOf("/")+1)//cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_FILENAME))
completeListener!!.ondownloadComplete(localName,localFile,null)
} else if (DownloadManager.STATUS_FAILED == cursor.getInt(columnIndex)) {
completeListener!!.ondownloadFailled(cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_REASON)))
}
}else{
completeListener!!.ondownloadFailled("Download cancelled or failled")
}
cursor.close()
}
}else{
completeListener!!.ondownloadFailled("Download cancelled or failled")
}
context.unregisterReceiver(this)
}
}
}
fun getAudiofilePath(name:String):String{
return Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC)
.getAbsolutePath().toString() + "/" + name
}
fun downloadFile(context: Context,title: String,url: String?,uristring: Uri?, mimeType: String? = null,completeListener: DownloadCompleteListener) {
this.completeListener = completeListener
val guessFileName = URLUtil.guessFileName(url, null, mimeType)
if(url == null || url.isEmpty()){
completeListener!!.ondownloadComplete(title,url,uristring)
return
}
var audiofilepath = getAudiofilePath(guessFileName);
var applictionFile = File(audiofilepath);
if(isAllreadyAvailabel(context,applictionFile)){
completeListener!!.ondownloadComplete(applictionFile.name,applictionFile.absolutePath,null)
return
}
downloadManager = context!!.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
val downloadUri = Uri.parse(url)
val request = DownloadManager.Request(downloadUri)
request.apply {
setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE or DownloadManager.Request.NETWORK_WIFI)
//setAllowedOverRoaming(true)
// setTitle(guessFileName)
// setDescription(guessFileName)
// setVisibleInDownloadsUi(true)
allowScanningByMediaScanner()
// setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
//request.setDestinationUri(Uri.fromFile(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)))
setDestinationInExternalPublicDir(Environment.DIRECTORY_MUSIC, guessFileName)
context.registerReceiver(receiver, IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE))
downloadReference = downloadManager.enqueue(this)
}
}
fun getAllreadyDownloadAudioPath(context: Context,url:String,mimeType: String? = null):String {
val guessFileName = URLUtil.guessFileName(url, null, mimeType)
var audiofilepath = getAudiofilePath(guessFileName);
var applictionFile = File(audiofilepath);
if(isAllreadyAvailabel(context,applictionFile)){
return applictionFile.absolutePath
}
return ""
}
fun downloadVideo(context: Context,title: String, urlFromServer: String?, mimeType: String? = null,completeListener: DownloadCompleteListener) {
this.completeListener = completeListener
val guessFileName = URLUtil.guessFileName(urlFromServer, null, mimeType)
if(urlFromServer == null || urlFromServer.isEmpty()){
completeListener!!.ondownloadComplete(title,urlFromServer, Uri.EMPTY)
return
}
val directory = File(Environment.getExternalStorageDirectory().toString() + File.separator + "zingsharetemp")
directory.mkdirs()
// var audiofilepath = getAudiofilePath(guessFileName);
var applicationFile = File(directory!!.path+'/'+guessFileName);
if(isAllreadyAvailabel(context,applicationFile)){
completeListener!!.ondownloadComplete(applicationFile.name,applicationFile.absolutePath,null)
return
}
downloadManager = context!!.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
val downloadUri = Uri.parse(urlFromServer)
val request = DownloadManager.Request(downloadUri)
request.apply {
setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE or DownloadManager.Request.NETWORK_WIFI)
allowScanningByMediaScanner()
setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, guessFileName)
context.registerReceiver(receiver, IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE))
downloadReference = downloadManager.enqueue(this)
}
}
fun isAllreadyAvailabel(context: Context,applictionFile:File):Boolean{
if(applictionFile.canRead() && applictionFile.length()>0) {
return true
}else{
deleteFiles(applictionFile.absolutePath)
}
return false
}
}
fun download(){
DownloadHelper.downloadFile(context,
title,
url,
uristring,
"audio/*",
object : DownloadHelper.DownloadCompleteListener {
override fun ondownloadComplete(name: String, path: String?, uristring: Uri?) {
}
override fun ondownloadFailled(error: String) {
}
})
}
hope it will help you
Related
i am trying to create a video player app using kotlin , First of all I got the videos files by using MediaStore , than store this in ArrayList so far it's been perfect but When I made a folder list of videos, I tried to find out the size of those folders and how many video files there are in those folders, but I failed. like this (Image)
Check this image for more clear
This is my data class code (VideoItem.Kt)
import android.net.Uri
data class VideoItem(
val id: String,
val title: String,
val duration: Long = 0,
val folderName: String,
val size: String,
val path: String,
val dateAdded: String,
val artUri: Uri
)
data class FolderItem(
val id: String,
val folderName: String,
val folderSize: Long
)
This is my MainActivity Code To get Allvideos Using MediaStore
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
companion object {
lateinit var videoList: ArrayList<VideoItem>
lateinit var folderList: ArrayList<FolderItem>
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
folderList = ArrayList()
videoList = getAllVideos()
setFragment(VideoviewFragment())
}
private fun setFragment(fragment: Fragment) {
val transaction = supportFragmentManager.beginTransaction()
transaction.replace(R.id.FrameLayout, fragment)
transaction.disallowAddToBackStack()
transaction.commit()
}
#SuppressLint("Recycle", "Range")
private fun getAllVideos(): ArrayList<VideoItem> {
val tempList = ArrayList<VideoItem>()
val tempFolderList = ArrayList<String>()
val projection = arrayOf(
MediaStore.Video.Media.TITLE,
MediaStore.Video.Media.SIZE,
MediaStore.Video.Media._ID,
MediaStore.Video.Media.BUCKET_DISPLAY_NAME,
MediaStore.Video.Media.DATA,
MediaStore.Video.Media.DATE_ADDED,
MediaStore.Video.Media.DURATION,
MediaStore.Video.Media.BUCKET_ID
)
val cursor = this.contentResolver.query(
MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
projection,
null,
null,
MediaStore.Video.Media.DATE_ADDED + " DESC"
)
if (cursor != null)
if (cursor.moveToNext())
do {
val titleC =
cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media.TITLE))
val idC = cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media._ID))
val folderNameC =
cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media.BUCKET_DISPLAY_NAME))
val folderIdC =
cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media.BUCKET_ID))
val sizeC = cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media.SIZE))
val pathC = cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media.DATA))
val dateAddedC =
cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media.DATE_ADDED))
val durationC =
cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media.DURATION))
.toLong()
try {
val file = File(pathC)
val artUriC = Uri.fromFile(file)
val video = VideoItem(
title = titleC,
id = idC,
folderName = folderNameC,
size = sizeC,
path = pathC,
duration = durationC,
dateAdded = dateAddedC,
artUri = artUriC
)
if (file.exists()) tempList.add(video)
//for adding Folders
if (!tempFolderList.contains(folderNameC)) {
tempFolderList.add(folderNameC)
val folderSizeC = getFileLength(pathC)
folderList.add(
FolderItem(
id = folderIdC,
folderName = folderNameC,
folderSize = folderSizeC
)
)
}
} catch (_: Exception) {
}
} while (cursor.moveToNext())
cursor?.close()
return tempList
}
private fun getFileLength(path: String?): Long {
return if (!isExistFile(path)) 0 else File(path.toString()).length()
}
private fun isExistFile(path: String?): Boolean {
val file = File(path.toString())
return file.exists()
}
}
This is my RecyclerviwAdapter Code(FolderAdapter.kt)
class FoldersAdapter(private val context: Context, private var foldersList: ArrayList<FolderItem>) :
RecyclerView.Adapter<FoldersAdapter.MyHolder>() {
class MyHolder(binding: FolderItemBinding) : RecyclerView.ViewHolder(binding.root) {
val folderName = binding.folderName
val noofFiles = binding.nooffiles
val folderSize = binding.foldersize
val root = binding.root
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyHolder {
return MyHolder(FolderItemBinding.inflate(LayoutInflater.from(context), parent, false))
}
override fun onBindViewHolder(holder: MyHolder, position: Int) {
holder.folderName.text = foldersList[position].folderName
val size: Long = foldersList[position].folderSize
holder.folderSize.text = android.text.format.Formatter.formatFileSize(context, (size))
holder.root.setOnClickListener {
val intent = Intent(context, FolderVideosActivity::class.java)
intent.putExtra("position", position)
ContextCompat.startActivity(context, intent, null)
}
}
override fun getItemCount(): Int {
return foldersList.size
}
}
This is my all codes now please check out all code and suggest the best.
Thank you
Use this function for size
private fun getFolderSize(f: File): Long {
var size: Long = 0
if (f.isDirectory) {
for (file in f.listFiles()!!) {
size += getFolderSize(file)
}
} else {
size = f.length()
}
return size
}
And Count number of files Use this
val length = File("/path/to/folder").listFiles()?.size
Hey i have this working FileWrite routine which i can simply call with
writeFile("Filename as String","Filetext as String")
but i cant read back the File i tried many solutions. I just want to call the read routine like this:
readFile("Filename as String") and file data should go to Sting: "txtfromfile"
`fun writeFile(name : String, data : String) {
val contentValues = ContentValues().apply {
put(MediaStore.MediaColumns.DISPLAY_NAME, name)
put(MediaStore.MediaColumns.MIME_TYPE, "text/plain")
put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DOCUMENTS + "/Sunny/")
}
val extVolumeUri: Uri = MediaStore.Files.getContentUri("external")
// query for the file
val cursor: Cursor? = contentResolver.query(
extVolumeUri,
null,
MediaStore.MediaColumns.DISPLAY_NAME + " = ? AND " + MediaStore.MediaColumns.MIME_TYPE + " = ?",
arrayOf(name, "text/plain"),
null
)
var fileUri: Uri? = null
// if file found
if (cursor != null && cursor.count > 0) {
// get URI
while (cursor.moveToNext()) {
val nameIndex = cursor.getColumnIndex(MediaStore.MediaColumns.DISPLAY_NAME)
if (nameIndex > -1) {
val displayName = cursor.getString(nameIndex)
if (displayName == name) {
val idIndex = cursor.getColumnIndex(MediaStore.MediaColumns._ID)
if (idIndex > -1) {
val id = cursor.getLong(idIndex)
fileUri = ContentUris.withAppendedId(extVolumeUri, id)
}
}
}
}
cursor.close()
} else {
// insert new file otherwise
fileUri = contentResolver.insert(extVolumeUri, contentValues)
}
if (fileUri != null) {
val os = contentResolver.openOutputStream(fileUri, "wt")
if (os != null) {
os.write(data.toByteArray())
os.close()
}
}
}`
i tryed numerous read Routines
But I can't find any that I can call like my write routine
i tried this but it gives me "java.io.FileNotFoundException: open failed: ENOENT (No such file or directory)"
fun readFile(name : String) {
val contentValues = ContentValues().apply {
put(MediaStore.MediaColumns.DISPLAY_NAME, name)
put(MediaStore.MediaColumns.MIME_TYPE, "text/plain")
put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DOCUMENTS + "/Sunny/")
}
val extVolumeUri: Uri = MediaStore.Files.getContentUri("external")
var fileUri: Uri? = null
fileUri = contentResolver.insert(extVolumeUri, contentValues)
val os = fileUri?.let { contentResolver.openInputStream(it) }
if (os != null) {
txtfromfile = os.read().toString()
os.close()
}
}
I am trying to save video, created from custom application, to the specific folder inside DCIM folder, side by side to original camera folder.
private fun recordVideo() {
val intent = Intent(MediaStore.ACTION_VIDEO_CAPTURE)
takeVideo.launch(intent)
}
private val takeVideo = registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) {
if (it.resultCode == Activity.RESULT_OK) {
Log.i(
"VIDEO_RECORD_TAG ", "Video is available at ${
it.data?.data?.let { it1 -> getRealPathFromURI(it1) }
}"
)
saveMediaFile(
it.data?.data?.let { it1 -> getRealPathFromURI(it1) }, "MyVideoName"
)
}
}
private fun saveMediaFile(filePath: String?, fileName: String) {
filePath?.let {
val values = ContentValues().apply {
put(MediaStore.Video.Media.DISPLAY_NAME, fileName)
val mExtension = MimeTypeMap.getFileExtensionFromUrl(filePath)
put(MediaStore.Video.Media.MIME_TYPE, MimeTypeMap.getSingleton().getMimeTypeFromExtension(mExtension))
put(MediaStore.Video.Media.RELATIVE_PATH, Environment.DIRECTORY_MOVIES + "/${getString(R.string.app_name)}/")
put(MediaStore.Video.Media.IS_PENDING, 1)
}
val fileUri = contentResolver.insert(
MediaStore.Video.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY),
values
)
fileUri?.let {
contentResolver.openFileDescriptor(fileUri, "w").use { descriptor ->
descriptor?.let {
FileOutputStream(descriptor.fileDescriptor).use { out ->
val videoFile = File(filePath)
FileInputStream(videoFile).use { inputStream ->
val buf = ByteArray(8192)
while (true) {
val sz = inputStream.read(buf)
if (sz <= 0) break
out.write(buf, 0, sz)
}
}
}
}
}
values.clear()
values.put(MediaStore.Video.Media.IS_PENDING, 0)
contentResolver.update(fileUri, values, null, null)
}
}
}
private fun getRealPathFromURI(contentUri: Uri): String? {
var cursor: Cursor? = null
return try {
val proj = arrayOf(MediaStore.Images.Media.DATA)
cursor = contentResolver.query(contentUri, proj, null, null, null)
val columnIndex = cursor?.getColumnIndexOrThrow(MediaStore.Images.Media.DATA)
cursor?.moveToFirst()
columnIndex?.let { cursor?.getString(it) }
} catch (e: Exception) {
Log.e("TAG", "getRealPathFromURI Exception : $e")
""
} finally {
cursor?.close()
}
}
Using this code, folder is created, video is stored as well, but in camera folder I have the same video with original name.
I would like to have only custom created folder with stored videos.
Any suggestion ?
Thanks
I want to send a video to the telegram app via Intent but when I send it, it sends as a file, (same happens with images). Is there any trick to specify how you want to send it? (Because from the gallery it sends the same video playable)
function for sending via Intent
private fun shareItem(fileName: String) {
Log.i(TAG, "shareItem: ")
val videoContentUri = FileProvider.getUriForFile(requireContext(),
"${activity?.applicationContext?.packageName}.provider",
File(LocalFilesRepository.getFullVideoPath(fileName, requireContext()))
)
Log.i("TAG", "shareItem: $videoContentUri")
val shareIntent: Intent = Intent().apply {
action = Intent.ACTION_SEND
flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
putExtra(Intent.EXTRA_STREAM, videoContentUri)
type = "video/mp4"
}
startActivity(Intent.createChooser(shareIntent, resources.getText(R.string.send_to)))
}
...
fun getFullVideoPath(fileName: String, context: Context) =
context.getExternalFilesDir(Environment.DIRECTORY_MOVIES).toString() + File.separatorChar + fileName
videoContentUri looks like this content://com.dmytroa.appname.provider/external_files/emulated/0/Android/data/com.dmytroa.appname/files/Movies/1625360538459.mp4
If someone is interested I solved it by just saving a file temporarily at the public storage and then returning Uri from Mediastore.
fun createTemporaryCopyInPublicStorage(file: File, context: Context): Uri? {
val fileName = "tmp"
return if(Build.VERSION.SDK_INT >= 29) {
val uri = findCreatedTemporaryUri(context, fileName, TEMPORARY_DIR_Q)
copyVideoQAndAbove(context, file, uri, fileName, TEMPORARY_DIR_Q)
} else {
val uri = findCreatedTemporaryUri(context, fileName, TEMPORARY_DIR_BELOWQ)
copyVideoBelowQ(context, file, uri, fileName, TEMPORARY_DIR_BELOWQ)
}
}
private fun findCreatedTemporaryUri(context: Context, fileName: String, path: String): Uri? {
val collection = if(Build.VERSION.SDK_INT >= 29) {
MediaStore.Video.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
} else {
MediaStore.Video.Media.EXTERNAL_CONTENT_URI
}
val selection = if (Build.VERSION.SDK_INT >= 29) {
"${MediaStore.Video.Media.TITLE} = ? " +
"AND " +
"${MediaStore.Video.Media.RELATIVE_PATH} = ? "
} else {
"${MediaStore.Video.Media.TITLE} = ? " +
"AND " +
"${MediaStore.Video.Media.DATA} = ? "
}
val args = if (Build.VERSION.SDK_INT >= 29) {
arrayOf(fileName, path)
} else {
arrayOf(fileName, File(path, fileName).absolutePath)
}
context.contentResolver.query(
collection,
arrayOf(MediaStore.Video.Media._ID
),
selection,
args,
null
).use { cursor ->
return if (cursor != null && cursor.moveToFirst()) {
val columnIndexID = cursor.getColumnIndexOrThrow(MediaStore.Video.Media._ID)
val id = cursor.getLong(columnIndexID)
Log.i(TAG, "findCreatedTemporaryUri: " +
"contentUri was already added $id $path $fileName")
Uri.withAppendedPath(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, "$id")
} else {
null
}
}
}
#RequiresApi(Build.VERSION_CODES.Q)
private fun copyVideoQAndAbove(context: Context,
fileToCopy: File,
uri: Uri?,
fileName: String,
relPath: String): Uri? {
val contentDetails = ContentValues().apply {
put(MediaStore.Video.Media.IS_PENDING, 1)
}
val contentUri = if (uri != null) {
context.contentResolver.update(uri, contentDetails, null, null)
uri
} else {
Log.i(TAG, "saveVideoQAndAbove: contentUri insert")
contentDetails.apply {
put(MediaStore.Video.Media.DISPLAY_NAME, fileName)
put(MediaStore.Video.Media.MIME_TYPE, "video/mp4")
put(MediaStore.Video.Media.RELATIVE_PATH, relPath)
}
val collection = MediaStore.Video.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
context.contentResolver.insert(collection, contentDetails)
}
return contentUri?.let { createdUri ->
try {
context.contentResolver.openFileDescriptor(createdUri, "w").use { pfd ->
ParcelFileDescriptor.AutoCloseOutputStream(pfd).write(fileToCopy.readBytes())
}
} catch (e: IOException) {
e.printStackTrace()
}
contentDetails.clear()
contentDetails.put(MediaStore.Video.Media.IS_PENDING, 0)
context.contentResolver.update(createdUri, contentDetails, null, null)
createdUri
}
}
private fun copyVideoBelowQ(context: Context,
fileToCopy: File,
uri: Uri?,
fileName: String,
dstParentPath: String): Uri? {
val dstDir = File(dstParentPath)
if (!dstDir.exists())
dstDir.mkdirs()
val fileToCreate = File(dstDir, fileName)
fileToCreate.delete()
fileToCreate.createNewFile()
Log.i(TAG, "saveVideo: created ${fileToCreate.name}")
try {
fileToCopy.inputStream().use { input ->
fileToCreate.outputStream().use { output ->
input.copyTo(output, 2 * 1024)
Log.i(TAG, "saveVideo: finished ${fileToCreate.path}")
}
}
return uri ?: let {
val values = ContentValues().apply {
put(MediaStore.Video.Media.TITLE, fileToCreate.name)
put(MediaStore.Video.Media.MIME_TYPE, "video/mp4")
put(MediaStore.Video.Media.DATA, fileToCreate.path)
}
context.contentResolver.insert(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, values)
}
} catch (e: IOException) {
e.printStackTrace()
}
return null
}
private val TEMPORARY_DIR_Q = Environment.DIRECTORY_MOVIES + File.separator +
"APPNAME" + File.separator +
"temporary" + File.separator
private val TEMPORARY_DIR_BELOWQ = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_MOVIES).absolutePath + File.separator +
"APPNAME" + File.separator +
"temporary" + File.separator
I'm a beginner in Android programming.
I'm writing an application to list all video file in a folder and display information of all videos in the folder. But when i try to get the video duration it return null and i can't find the way to get it.
Any one can help me?
Below is my code:
Uri uri = Uri.parse("content://media/external/video/media/9");
Cursor cursor = MediaStore.Video.query(res, data.getData(), new String[]{MediaStore.Video.VideoColumns.DURATION});
if(cursor.moveToFirst()) {
String duration = cursor.getString(0);
System.out.println("Duration: " + duration);
}
Use MediaMetadataRetriever to retrieve media specific data:
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
//use one of overloaded setDataSource() functions to set your data source
retriever.setDataSource(context, Uri.fromFile(videoFile));
String time = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
long timeInMillisec = Long.parseLong(time );
retriever.release()
I think the easiest way is:
MediaPlayer mp = MediaPlayer.create(this, Uri.parse(uriOfFile));
int duration = mp.getDuration();
mp.release();
/*convert millis to appropriate time*/
return String.format("%d min, %d sec",
TimeUnit.MILLISECONDS.toMinutes(duration),
TimeUnit.MILLISECONDS.toSeconds(duration) -
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(duration))
);
Kotlin Extension Solution
Here is the way to fetch media file duration in Kotlin
fun File.getMediaDuration(context: Context): Long {
if (!exists()) return 0
val retriever = MediaMetadataRetriever()
retriever.setDataSource(context, Uri.parse(absolutePath))
val duration = retriever.extractMetadata(METADATA_KEY_DURATION)
retriever.release()
return duration.toLongOrNull() ?: 0
}
If you want to make it safer (Uri.parse could throw exception), use this combination. The others are generally just useful as well :)
fun String?.asUri(): Uri? {
try {
return Uri.parse(this)
} catch (e: Exception) {
}
return null
}
val File.uri get() = this.absolutePath.asUri()
fun File.getMediaDuration(context: Context): Long {
if (!exists()) return 0
val retriever = MediaMetadataRetriever()
retriever.setDataSource(context, uri)
val duration = retriever.extractMetadata(METADATA_KEY_DURATION)
retriever.release()
return duration.toLongOrNull() ?: 0
}
Not necessary here, but generally helpful additional Uri extensions
val Uri?.exists get() = if (this == null) false else asFile().exists()
fun Uri.asFile(): File = File(toString())
I don't think you post your URI into the mediastore video query
Uri uri = Uri.parse("content://media/external/video/media/9");
Cursor cursor = MediaStore.Video.query(res, data.getData(), new String[]{MediaStore.Video.VideoColumns.DURATION});
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
retriever.setDataSource(uriOfFile);
long duration = Long.parseLong(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION))
int width = Integer.valueOf(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH));
int height = Integer.valueOf(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT));
retriever.release();
public static long getDurationOfSound(Context context, Object soundFile)
{
int millis = 0;
MediaPlayer mp = new MediaPlayer();
try
{
Class<? extends Object> currentArgClass = soundFile.getClass();
if(currentArgClass == Integer.class)
{
AssetFileDescriptor afd = context.getResources().openRawResourceFd((Integer)soundFile);
mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
afd.close();
}
else if(currentArgClass == String.class)
{
mp.setDataSource((String)soundFile);
}
else if(currentArgClass == File.class)
{
mp.setDataSource(((File)soundFile).getAbsolutePath());
}
mp.prepare();
millis = mp.getDuration();
}
catch(Exception e)
{
// Logger.e(e.toString());
}
finally
{
mp.release();
mp = null;
}
return millis;
}
MediaPlayer mpl = MediaPlayer.create(this,R.raw.videoFile);
int si = mpl.getDuration();
This will give the duration of the video file
object MediaHelper {
const val PICK_IMAGE_FROM_DEVICE = 100
const val PICK_MEDIA_FROM_DEVICE = 101
fun openPhoneGalleryForImage(fragment: Fragment){
Intent(Intent.ACTION_GET_CONTENT).run {
this.type = "image/*"
fragment.startActivityForResult(this, PICK_IMAGE_FROM_DEVICE)
}
}
fun openPhoneGalleryForMedia(fragment: Fragment){
Intent(Intent.ACTION_GET_CONTENT).run {
this.type = "*/*"
fragment.startActivityForResult(this, PICK_MEDIA_FROM_DEVICE)
}
}
fun getMediaType(context: Context, source: Uri): MediaType? {
val mediaTypeRaw = context.contentResolver.getType(source)
if (mediaTypeRaw?.startsWith("image") == true)
return MediaType.Image
if (mediaTypeRaw?.startsWith("video") == true)
return MediaType.Video
return null
}
fun getVideoDuration(context: Context, source: Uri): Long? {
if (getMediaType(context, source) != MediaType.Video)
return null
val retriever = MediaMetadataRetriever()
retriever.setDataSource(context, source)
val duration = retriever.extractMetadata(METADATA_KEY_DURATION)
retriever.release()
return duration?.toLongOrNull()
}
}
enum class MediaType {
Image {
override val mimeType: String = "image/jpeg"
override val fileExtension: String = ".jpg"
},
Video {
override val mimeType: String = "video/mp4"
override val fileExtension: String = ".mp4"
};
abstract val mimeType: String
abstract val fileExtension: String
}
fun File.getVideoDuration(context: Context): Long {
context.contentResolver.query(toUri(), arrayOf(MediaStore.Video.Media.DURATION), null, null, null)?.use {
val durationColumn = it.getColumnIndexOrThrow(MediaStore.Video.Media.DURATION)
it.moveToFirst()
return it.getLong(durationColumn)
}
return 0