在更新的Android Q中,许多事情发生了变化,特别是作用域存储和file://
URI的逐渐弃用。问题是缺乏关于如何在Android Q设备上正确处理媒体文件的文档。
我有一个媒体文件(音频)管理应用程序,但我还找不到一个可靠的方法告诉操作系统,我对一个文件执行了更改,以便它可以更新其纵隔记录。
选项1:MediaScannerService
MediaScannerConnection.scanFile(context, new String[]{ filePath }, new String[]{"audio/*"}, new MediaScannerConnection.OnScanCompletedListener() {
@Override
public void onScanCompleted(String s, Uri uri) {
}
});
文件://
URI一起工作文件://
来自辅助存储(如可移动存储)的URI内容://
URI选项2:广播
context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, uri));
audiofileContentValues
是mediastore.audio.audioColumns
中的一些列值。
基于文件://
URI的旧方法:
Uri uri = MediaStore.Audio.Media.getContentUriForPath(file_path);
newUri = context.getContentResolver().insert(uri, AudioFileContentValues);
mediastore.audio.media.GetContenturiforPath
不推荐使用更新的方法基于我可以从文档中整理的内容:
Uri collection = MediaStore.Audio.Media.getContentUri(correctVolume);
newUri = context.getContentResolver().insert(collection, AudioFileContentValues);
其中,corretvolume
将是来自主存储的external
,而对于辅助存储,则类似于0000-0000
,具体取决于文件所在的位置。
content://media/external/audio/media/125
,但对于位于主存储器中的文件,不在纵隔存储中持久化任何记录这些或多或少都是以前Android版本中可用的方法,但现在没有一种方法允许我通知系统我更改了一些音频文件元数据,并让Android更新MediaStore记录。事件尽管选项#1部分起作用,但这绝不可能是一个有价值的解决方案,因为它显然不支持内容URI。
在Android Q上有没有可靠的方法触发媒体扫描,尽管文件位于何处?根据Google的说法,我们甚至不应该关心文件位置,因为我们很快将只使用内容URI。纵隔在我看来一直有点令人沮丧,但现在的情况相当糟糕。
我现在也在纠结于这个问题。
我想你想做的事情一旦你上了Android Q,你就不能再做了,因为你不允许访问Q上的音乐目录,你只允许创建和访问你创建的目录中的文件。您没有创建音乐目录。
现在媒体的每一个变化都要发生,都要抛出纵隔。所以你预先插入你的音乐文件,然后从纵隔腔获得一个输出流来写入它。在介质上的Q上的所有更改都应该在纵隔室中完成,因此您将更改通知纵隔室甚至不会再发生了,因为您从来没有直接访问过该文件。
这有一个巨大的鱼子酱,所有的新东西在纵隔使这成为可能,并不存在于老版本的Android。所以我现在确实认为你将需要执行每件事两次,可悲的是。至少如果你想积极地影响你的音乐保存到哪里,那就是。
这两个纵隔柱在Q中是新的,在Q之前不存在,你可能需要在Q中使用
mediastore.audio.media.relative_path
使用它可以影响保存它的路径。所以我将“music/myappname/mylibraryname”放在那里,这样就可以将“song.mp3”保存到“music/myappname/mylibraryname/song.mp3”mediastore.audio.media.is_pending
在歌曲仍在编写时应将其设置为1,然后可以将其更新为0。我现在也开始在Android版本的if检查中实现了两次。真烦人。我不想这么做。但这似乎是唯一的办法。
我将在这里放一些代码,说明我是如何在Android.q和下面的文件中插入音乐的。并不完美。我必须为Q指定MIME类型,因为flacs现在不知怎么变成了.flac.mp3,因为它似乎不太能实现这一点。
所以,无论如何,这是一个部分,我已经更新工作与Q和之前,它下载一个音乐文件从音乐播放器在我的NAS。这个应用程序是用kotlin编写的,不确定这对你来说是不是一个问题。
override fun execute(library : Library, remoteApi: RemoteApi, ctx: Context) : Boolean {
var success = false
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
val values = ContentValues().apply {
put(MediaStore.Audio.Media.RELATIVE_PATH, library.rootFolderRelativePath)
put(MediaStore.Audio.Media.DISPLAY_NAME, remoteLibraryEntry.getFilename())
put(MediaStore.Audio.Media.IS_PENDING, 1)
}
val collection = MediaStore.Audio.Media
.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
val uri = ctx.contentResolver.insert(collection, values)
ctx.contentResolver.openOutputStream(uri!!).use {
success = remoteApi.downloadMusic(remoteLibraryEntry, it!!)
}
if(success) {
values.clear()
val songId = JDrop.mediaHelper.getSongId(uri)
JDrop.db.music.insert(Music(mediaStoreId = songId, remoteId = remoteLibraryEntry.remoteId, libraryId = library.id))
values.put(MediaStore.Audio.Media.IS_PENDING, 0)
ctx.contentResolver.update(uri, values, null, null)
} else {
ctx.contentResolver.delete(uri, null, null)
}
} else {
val file = File("${library.rootFolderPublicDirectory}/${remoteLibraryEntry.getFilename()}")
if(file.exists()) file.delete()
success = remoteApi.downloadMusic(remoteLibraryEntry, file.outputStream())
if (success) {
MediaScannerConnection.scanFile(ctx, arrayOf(file.path), arrayOf("audio/*")) { _, uri ->
val songId = JDrop.mediaHelper.getSongId(uri)
JDrop.db.music.insert(Music(mediaStoreId = songId, remoteId = remoteLibraryEntry.remoteId, libraryId = library.id))
}
}
}
return success
}
纵隔辅助器的方法是这样的
fun getSongId(uri : Uri) : Long {
val cursor = resolver.query(uri, arrayOf(Media._ID), null, null, null)
return if(cursor != null && cursor.moveToNext()) {
val idIndex = cursor.getColumnIndex(Media._ID)
val id = cursor.getLong(idIndex)
cursor.close()
id
} else {
cursor?.close()
-1
}
}
当您没有指定MIME类型时,似乎会假设mp3是MIME类型。所以.flac文件将被保存为name.flac.mp3,因为如果没有mp3文件类型,它会添加mp3文件类型,并且认为它是mp3。它不会为mp3文件添加另一个.mp3。我现在没有默剧类型...所以我想我现在就去做吧。
这可能回答不了你所有的问题。对我来说肯定不是。但这是一个有帮助的开始,有一个粗略的想法,他们甚至改变了什么开始。
对于删除和更新文件,它在Q上是一样的。如果您对纵隔条目调用delete,该文件将被删除。以前,你必须手动删除文件也。但如果你在Q上这么做,你的应用程序就会崩溃。因此,您必须再次检查您是否使用了Q或较旧版本的android,并采取适当的行动。
我正在使用存储访问框架将图像下载到外部sd卡。问题是这些图像不会出现在图库中。我试图通过发送DocumentFile uri来通知Android媒体扫描仪使用意图,但这似乎不起作用。下面是我如何尝试通知媒体扫描器添加了新图像: 有没有其他方法来通知Android添加了新图像?(我已经尝试了这里描述的方法,但我无法使用这些方法获得真实路径)
有人知道MSBuild的SonarQube扫描器是作为构建的一部分进行扫描并只将结果发回给SonarQube,还是EXE正在检测,我们可以将工件发送到Linux机器上的SonarQube进行分析,类似于使用sonar-scanner-cli扫描java工件的方式?
我试图通过DownloadManager下载一张图片,并将其显示在Gallery应用程序中,但我所做的一切都不起作用。根据文档,我认为这段代码就足够了: 但是当文件下载时,它不会出现在Gallery应用程序中。所以我尝试了一个下载接收器来手动添加它,如下所示: 那也不行。打印有“filename”标记的URI类似于content://downloads/my_downloads/97'而不是下载的
问题内容: Scanner.class 提供了许多有用的工具来分析数字,例如可以触发特定特征的 .hasNext ()和 .next_ _()方法。 在这样的某个地方,对于Date来说:第一次是要检测 String中的 日期,并根据格式调整响应( mm / dd / yy | dd / mm / yy | yyyymmdd ,是秒,是字母在里面,是四位数的年份,是负数…)。 编辑回应 扫描仪提供的
本文向大家介绍Android中扫描多媒体文件操作详解,包括了Android中扫描多媒体文件操作详解的使用技巧和注意事项,需要的朋友参考一下 这篇文章从系统源代码分析,讲述如何将程序创建的多媒体文件加入系统的媒体库,如何从媒体库删除,以及大多数程序开发者经常遇到的无法添加到媒体库的问题等。本人将通过对源代码的分析,一一解释这些问题。 Android中的多媒体文件扫描机制 Android提供了一个很棒
我找到了一些相关的答案,但没有一个能解释我是否真的需要Azure Media Services团队示例中的所有代码https://azure.microsoft.com/en-us/documentation/articles/media-services-copying-existing-blob/我只想把一个文件从blob上传到Azure Media Services。这样地: 但是我得到了