我正在尝试简单地添加音频文件。我的解决方案大多有效。但是当文件已经存在于MediaStore
. 我仔细查看过的一次也只存在于MediaStore
该位置的设备上没有文件。
val values = ContentValues().apply {
put(MediaStore.Audio.Media.RELATIVE_PATH, libraryPart.rootFolderRelativePath) // JDrop/1/1
put(MediaStore.Audio.Media.DISPLAY_NAME, remoteLibraryEntry.getFilename()) //12.mp3
put(MediaStore.Audio.Media.IS_PENDING, 1)
if(mimeType != null)
put(MediaStore.Audio.Media.MIME_TYPE, mimeType) // audio/mpeg3
}
val collection = MediaStore.Audio.Media
.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
var uri = ctx.contentResolver.insert(collection, values) // returns null for around 300/2000 files consistently
尝试插入该新文件时,Logcat 会输出以下内容。
2020-01-24 22:27:33.724 4015-7707/? E/SQLiteDatabase: Error inserting title_key= bucket_display_name=1 owner_package_name=shio.at.jdrop parent=79657 volume_name=external_primary title_resource_uri=null _display_name=12.mp3 mime_type=audio/mpeg3 _data=/storage/emulated/0/Music/JDrop/1/1/12.mp3 title= group_id=1569 artist_id=322 is_pending=1 date_added=1579901253 album_id=2958 primary_directory=Music secondary_directory=JDrop bucket_id=687581593 media_type=2 relative_path=Music/JDrop/1/1/ from {P:30220;U:10165}
android.database.sqlite.SQLiteConstraintException: UNIQUE constraint failed: files._data (code 2067 SQLITE_CONSTRAINT_UNIQUE)
at android.database.sqlite.SQLiteConnection.nativeExecuteForLastInsertedRowId(Native Method)
at android.database.sqlite.SQLiteConnection.executeForLastInsertedRowId(SQLiteConnection.java:879)
at android.database.sqlite.SQLiteSession.executeForLastInsertedRowId(SQLiteSession.java:790)
at android.database.sqlite.SQLiteStatement.executeInsert(SQLiteStatement.java:88)
at android.database.sqlite.SQLiteDatabase.insertWithOnConflict(SQLiteDatabase.java:1639)
at android.database.sqlite.SQLiteDatabase.insert(SQLiteDatabase.java:1494)
at com.android.providers.media.MediaProvider.insertFile(MediaProvider.java:3050)
at com.android.providers.media.MediaProvider.insertInternal(MediaProvider.java:3452)
at com.android.providers.media.MediaProvider.insert(MediaProvider.java:3240)
at android.content.ContentProvider$Transport.insert(ContentProvider.java:325)
at android.content.ContentProviderNative.onTransact(ContentProviderNative.java:164)
at android.os.Binder.execTransactInternal(Binder.java:1032)
at android.os.Binder.execTransact(Binder.java:1005)
这files._data
意味着该文件已经存在于MediaStore
. 没有文件JDrop/1/1/12.mp3
,它只是在MediaStore
,我需要以某种方式摆脱它或为现有MediaStore
条目获取一个 OutputStream 并相应地更新它。
我尝试使用以下代码查询ID
in没有成功。MediaStore
要么找出 要么ID
会URI
很好。此外MediaStore.Audio.Media.DATA
,自 SDK 29 起已弃用。所以我想在不使用它的情况下查询它。
if(uri == null) {
val id: Long = ctx.contentResolver.query(
collection,
arrayOf(BaseColumns._ID),
"${MediaStore.Audio.Media.RELATIVE_PATH}=? AND ${MediaStore.Audio.Media.DISPLAY_NAME}=?",
arrayOf(libraryPart.rootFolderRelativePath, remoteLibraryEntry.getFilename()),
null)?.use {
if (it.moveToNext())
it.getLong(it.getColumnIndex(BaseColumns._ID))
else null
} ?: return false
uri = Uri.withAppendedPath(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, id!!.toString())
}
编辑 1(查询 _data)
我现在还尝试_data
使用我知道无法插入的硬编码路径进行查询,但没有取得多大成功。
val id: Long = ctx.contentResolver.query(
collection,
arrayOf(BaseColumns._ID),
"${MediaStore.Audio.Media.DATA}=?",
arrayOf("/storage/emulated/0/Music/JDrop/1/1/12.mp3"),
null)?.use {
if (it.moveToNext())
it.getLong(it.getColumnIndex(BaseColumns._ID))
else null
} ?: return false
也返回 null 并返回 false。
编辑 2(查询所有内容并查看它返回的内容)
我尝试按照建议对整个集合进行一些测试查询。
class TestQueryObject(val id: Long, val relativePath: String, val displayName: String)
val results = mutableListOf<TestQueryObject>()
ctx.contentResolver.query(
collection,
arrayOf(MediaStore.Audio.Media._ID, MediaStore.Audio.Media.RELATIVE_PATH, MediaStore.Audio.Media.DISPLAY_NAME),
null,
null,
null)?.use {
while (it.moveToNext()) {
results.add(TestQueryObject(
id = it.getLong(it.getColumnIndex(MediaStore.Audio.Media._ID)),
relativePath = it.getString(it.getColumnIndex(MediaStore.Audio.Media.RELATIVE_PATH)),
displayName = it.getString(it.getColumnIndex(MediaStore.Audio.Media.DISPLAY_NAME))
))
}
}
var find12 = results.find { it.displayName == "12.mp3" }
它返回一个包含 2557 个条目的列表。作为第一个示例,名称是"5.mp3"
id 是79658
相对路径"Music/JDrop/1/1"
。前面有一个Music/
我不知道的。但 find12 仍然为空。
编辑 3(可能重要或不重要的其他想法)
还可能值得注意的是,它不会发生在我使用 android 10 创建的 Android 模拟器上。但它会发生在我的 OnePlus 6 上,其中包含大约 300 多个文件,并且适用于所有其余部分。我已经在 Android 9 中使用该程序,然后升级到 Android 10。我在某处读到,当您升级到 10 时,来自 Android 9 的文件可能被认为是孤立的,而不是属于您的应用程序(至少当您卸载创建它们的应用程序)。所以我可能无法再访问我正在寻找的媒体商店条目?不过,我也想过。现在无需任何许可,任何应用程序都可以访问阅读媒体。因此,如果这是一个访问问题,则在尝试写入时应该会失败。不是在阅读或找到它时。
此外,正如@CommonsWare 提到的那样,IS_PENDING
可能仍设置为1
. 我确实将其设置回0
我发布的代码下方。但是,每当我在调试时关闭程序时,该代码可能永远不会执行,因为它将在下载和写入文件的部分进行 9/10 次,因为这是迄今为止程序中发生的任何事情的最长时间。