package com.devrj.helium.data_model
import android.content.ContentUris.withAppendedId
import android.content.Context
import android.net.Uri
import android.os.CancellationSignal
import android.provider.MediaStore.Audio.Media.*
import com.devrj.helium.model.entity.TrackEntity
class MediaStoreDataStream(streamInfo: () -> Context) :
DataStream<Context, TrackEntity>(streamInfo) {
private var cancellationSignal: CancellationSignal? = null
companion object {
private const val COL_ID = 0
private const val COL_TITLE = 1
private const val COL_SIZE = 2
private const val COL_ARTIST = 3
private const val COL_ALBUM = 4
private const val COL_YEAR = 5
private const val COL_TRACK = 6
private const val COL_DATE_MODIFIED = 7
private const val COL_DATE_ADDED = 8
private const val COL_DISPLAY_NAME = 9
private const val COL_DATA = 10
val projection = arrayOf(
_ID,
TITLE,
SIZE,
ARTIST,
ALBUM,
YEAR,
TRACK,
DATE_MODIFIED,
DATE_ADDED,
DISPLAY_NAME,
DATA
)
}
override fun stopStream() {
super.stopStream()
cancellationSignal?.cancel()
}
override fun onStreamStarted() {
val context = streamInfo()
val contentResolver = context.contentResolver
cancellationSignal = CancellationSignal()
val trackQuery = contentResolver.query(
EXTERNAL_CONTENT_URI,
projection,
null,
null,
null,
cancellationSignal
)
trackQuery?.use { cursor ->
/*
Cache column indices
*/
val columns = Array(projection.size) { i ->
cursor.getColumnIndex(projection[i])
}
/*
Per entity
*/
while (cursor.moveToNext()) {
val columnId = cursor.getLong(columns[COL_ID])
val locationURI: Uri = withAppendedId(INTERNAL_CONTENT_URI, columnId)
////////////////////////////////////////////////////
//////////////////CREATE NEW ENTITY/////////////////
////////////////////////////////////////////////////
val newTrack = TrackEntity(columnId)
newTrack.apply {
uri = locationURI.path.toString()
size = cursor.getLong(columns[COL_SIZE])
title = cursor.getString(columns[COL_TITLE])
artist = cursor.getString(columns[COL_ARTIST])
album = cursor.getString(columns[COL_ALBUM])
track = cursor.getInt(columns[COL_TRACK])
dateModified = cursor.getLong(columns[COL_DATE_MODIFIED])
dateAdded = cursor.getLong(columns[COL_DATE_ADDED])
dateAccessed = cursor.getLong(columns[COL_DATE_ADDED])
year = cursor.getLong(columns[COL_YEAR])
displayName = cursor.getString(columns[COL_DISPLAY_NAME])
filePath = cursor.getString(columns[COL_DATA])
}
send(newTrack)
newTrack.deb()
}
}
}
}
Недавно я начал изучать API MediaStore, и, поскольку я создаю приложение проигрывателя musi c, я подумал, что было бы полезно перейти на него из-за всех преимуществ производительности.
Однако, Я не могу сыграть ни одной песни или восстановить ее обложку. Как мне этого добиться?
Вот как я пытаюсь воспроизвести песню
val resolver: ContentResolver = onContextRequest!!.onRequest().contentResolver
val mode = "rw"
try {
val uri = Uri.parse(Stem.get().loadedTrack.data!!.uri)
uri.toast(onContextRequest!!.onRequest())
resolver.openFileDescriptor(uri, mode).use {
player!!.setDataSource(it!!.fileDescriptor)
}
} catch (e: IOException) {
e.printStackTrace()
"ERROR $e".longToast(onContextRequest!!.onRequest())
}
И я получаю исключение FileNotFoundException
ERROR java.io.FileNotFoundException: No content provider: /internal/audio/<some_id>
Прежде чем я смог установить источник данных на путь к файлу, и он работал нормально, но этот метод не самый эффективный.
В официальной документации android указано, как это сделать. Что я и делаю
https://developer.android.com/training/data-storage/shared/media#open -файл
Это все разрешения, которые я объявил (да, они предоставляются во время выполнения)
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />