[android : kotlin] MediaStore.Audio.Media로 부터 Uri를 통해 duration (노래 총 재생시간) 가져오는 방법
MediaStore.Audio.Media.DURATION를 통해 노래파일의 재생시간을 알고 싶었으나 값을 알수 없었다. 모든 노래에서 동일한 값으로 6이 넘어왔다.
val mCursorCols = arrayOf(
MediaStore.Audio.Media._ID,
MediaStore.Audio.Media.ARTIST,
MediaStore.Audio.Media.TITLE,
MediaStore.Audio.Media.ALBUM,
MediaStore.Audio.Media.DATA,
MediaStore.Audio.Media.ALBUM_ID,
MediaStore.Audio.Media.DURATION
)
fun getMediaSongList(context: Context) : ArrayList<MusicViewModel> {
val mCursorCols = arrayOf(
MediaStore.Audio.Media._ID,
MediaStore.Audio.Media.ARTIST,
MediaStore.Audio.Media.TITLE,
MediaStore.Audio.Media.ALBUM,
MediaStore.Audio.Media.DATA,
MediaStore.Audio.Media.ALBUM_ID,
MediaStore.Audio.Media.DURATION
)
var cur = context.contentResolver.query(
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
mCursorCols,
null,
null,
null
)
if (cur != null && cur.moveToFirst()) {
lateinit var title: String
lateinit var artist: String
lateinit var album: String
// - MediaStore.Audio.Albums
// - MediaStore.Audio.Artists
// - MediaStore.Audio.Genres
// - MediaStore.Audio.Playlists
// - MediaStore.Audio.Media
//
// * Nested Inteface
// - MediaStore.Audio.AlbumColumns : 앨범을 나타내는 컬럼
// - MediaStore.Audio.ArtistColumns : 연주자를 나타내는 컬럼
// - MediaStore.Audio.GenresColumns : 쟝르를 나타내는 컬럼
// - MediaStore.Audio.PlaylistsColumns : 곡목록을 나타내는 컬럼
// - MediaStore.Audio.AudioColumns : 여러개의 테이블에서 나타나는 audio file을 위한 컬럼
val titleColumn = cur.getColumnIndex(MediaStore.Audio.Media.TITLE)
val artistColumn = cur.getColumnIndex(MediaStore.Audio.Media.ARTIST)
val albumColumn = cur.getColumnIndex(MediaStore.Audio.Media.ALBUM)
val idColumn = cur.getColumnIndex(MediaStore.Audio.Media._ID) //2020.07
val duration = cur.getColumnIndex(MediaStore.Audio.Media.DURATION)
try {
do {
title = cur.getString(titleColumn)
artist = cur.getString(artistColumn)
album = cur.getString(albumColumn)
val albumIds = cur.getLong(cur.getColumnIndex(MediaStore.Audio.Media.ALBUM_ID))
//Log.e("TAG", "title = $title albumIds=$albumIds] duration: $duration")
val audioId = cur.getLong(idColumn)
val sArtworkUri = Uri.parse("content://media/external/audio/albumart")
val sAlbumArtUri = ContentUris.withAppendedId(sArtworkUri, albumIds)
//android.util.Log.i("jinsu", "sAlbumArtUri = " + sAlbumArtUri + "]");
val externalUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
val contentUri = ContentUris.withAppendedId(externalUri, audioId)
// val mediaId: String,
// val title: String,
// val subtitle: String?,
// val artist: String?,
// val albumArtUri: String,
// val contentUri: Uri,
// val duration: String
val musicVo = MusicViewModel(
audioId,
title,
"서브타이틀",
artist,
sAlbumArtUri,
contentUri,
//cur.getLong(duration) //-1L
50000 //-1L
)
musicList.add(musicVo)
} while (cur.moveToNext())
} catch (ee: IllegalStateException) {
ee.printStackTrace()
} catch (se: SecurityException) {
se.printStackTrace()
//songsList = java.util.ArrayList<MusicVo>()
} catch (e: Exception) {
e.printStackTrace()
} finally {
cur?.close()
}
}
return musicList
}
}
MediaStyle Notification을 구현할때 duration 값을 가져와 SeekBar에 설정해야함으로 필요했다.
방법은 생각보다 간단했다. 모르고 있으면 어려울뿐!!! MediaMetadataRetriever 클래스를 사용하여 duration 값을 가져올 수 있었다.
fun getMediaDuration(context: Context, uri: Uri): Long {
var metaRetriever:MediaMetadataRetriever = MediaMetadataRetriever()
return try {
//get total duration
metaRetriever.setDataSource(context, uri)
val duration: String =
metaRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)
//val millSecond : Int = duration
Log.e("TAG", "#### call MyMediaSessionCallback() : duration: $duration")
metaRetriever.release()
duration.toLongOrNull() ?: 0
} catch (exception: Exception) {
0
}
}
이제 SeekBar를 컨트롤 할 수 있는 방법을 찾아보자!!!!!
새로운 지식을 하나씩 알아감으로 느끼는 즐거움이 참으로 오랜만에 찾아왔다.
착오가 있었다. 기존 방법으로 가져올 수 있다. 코딩 오류이다. 아래 코드 스니펫처럼 가져와야 한다. 위 첫번째 스니펫 코드는 값을 가져오고 있는게 아니라 인덱스 번호를 전달 받고 있었다.
AS-IS
val duration = cur.getColumnIndex(MediaStore.Audio.Media.DURATION)
TO-BE
val duration = cur.getLong(cur.getColumnIndex(MediaStore.Audio.AudioColumns.DURATION))
[build.gradle(:app)]
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
android {
compileSdkVersion 29
defaultConfig {
applicationId "edu.kotlin.study"
minSdkVersion 23
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
// For Java compilers:
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.core:core-ktx:1.3.2'
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation "androidx.media:media:1.2.0"
implementation "androidx.recyclerview:recyclerview:1.1.0"
//implementation "com.android.support:support-media-compat:29.+"
// full exoplayer library
//implementation 'com.google.android.exoplayer:exoplayer:2.11.5'
implementation 'com.google.android.exoplayer:exoplayer-core:2.11.5'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}
[REFERENCE]
stackoverflow.com/questions/15394640/get-duration-of-audio-file/32901068
[연관 글 더보기]
[android : kotlin] 코틀린 Notification MediaStyle 사용시 SeekBar 설정 및 해제 하는 방법
[android : kotlin] 코틀린 RecyclerView 클릭시 미디어 재생 하는 방법 : MediaController ,SimpleExoPlayer
[android : kotlin] 코틀린 Notification setShowActionsInCompactView 사용 예제 : MediaStyle
[android : kotlin] 코틀린 Notification addAction 추가하는 방법(.apply) : Notification.Action.Builder