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()
}
}
}
}
我最近开始学习MediaStore API,并且由于我正在构建音乐播放器应用程序,因此我认为由于其所有性能优势而迁移到该应用程序将是有益的。但是,我似乎无法播放一首歌曲或检索其封面。我该如何实现?
这是我尝试播放歌曲的方式
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-file
这些都是我已经声明的所有权限(是的,它们在运行时被授予)
<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" />
我看不到EXTERNAL_CONTENT_URI
是什么。如果您使用的是Android Q,请使用
Uri mediaUri = MediaStore.Audio.Media.getContentUri(MediaStore.VOLUME_EXTERNAL);
然后生成文件的类似于ContentUri
的文件
contentUri = ContentUris.withAppendedId( MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, _id);
使用此uri启动MediaMetaRetriever以获取相册
MediaMetadataRetriever mmr = new MediaMetadataRetriever();
byte[] img = mmr.getEmbeddedPicture();
您可以像玩这个uri一样>>
mMediaplayer.setDataSource(mContext, uri);
希望有帮助。不要忘记设置运行权限。
GGK