2

似乎 MediaScanner 想要扫描我告诉它不要的文件。现在我想知道为什么。


我的应用程序从我的服务器下载了几个媒体文件,并在稍后通过播放列表显示它们。

为此,该应用程序使用 Android 系统的DownloadManager获取媒体文件。

使用Request.setDestinationUri(),下载将被保存到名为“pending”的getExternalCacheDir()的子目录中。

下载完成后,Android DownloadManager 会发送ACTION_DOWNLOAD_COMPLETE广播。然后,我的应用程序的广播侦听器将完成下载并将其从“待处理”文件夹移动到另一个名为“媒体”的文件夹。

所有这些都按预期工作。

但是,系统日志中充满了如下消息:

E/BitmapFactory(23779): Unable to decode stream: java.io.FileNotFoundException: /path/to/pending/image.jpg: open failed: ENOENT (No such file or directory)
E/JHEAD (23779): can't open '/path/to/pending/image.jpg'

E/StagefrightMetadataRetriever(25911): Unable to create data source for '/path/to/pending/video.mp4'.
E/MediaScannerJNI(23779): An error occurred while scanning file '/path/to/pending/video.mp4'.

显然,我的应用程序告诉 DownloadManager 将图像/视频下载到“待处理”目录。它按照它的指示执行并发送“我完成下载”广播。我的应用程序接收广播并将完整文件移动到“媒体”目录。片刻之后,MediaScanner(或其他东西)尝试扫描“待处理”文件夹中的已完成文件,并输入系统日志。

现在我想知道:为什么 MediaScanner 仍然试图读取这些文件?


根据 setDestinationUri 的 Android API 文档: “ MediaScanner不会扫描下载的文件。但可以通过调用 allowScanningByMediaScanner() 使其可扫描。” 我不调用该方法,因此不应扫描下载的文件。

接下来,我尝试在应用程序的缓存目录中放置一个空的.ignore ,并通过ACTION_MEDIA_SCANNER_SCAN_FILE提醒 MediaScanner .ignore-file 的存在,但错误消息仍然存在。

为了增加神秘感,这些文件不会出现在系统的图库或视频应用程序中,所以是的,媒体扫描仪会忽略它们。但仍然:为什么它在不需要的时候尝试读取它们?是 MediaScanner 还是其他系统服务?

4

2 回答 2

1

接下来,我尝试在应用程序的缓存目录中放置一个空的.ignore,并通过ACTION_MEDIA_SCANNER_SCAN_FILE 提醒MediaScanner .ignore-file 的存在,但错误消息仍然存在。

停止 Mediascanner 的魔法文件不是“.ignore”而是“.nomedia”。
来自 MediaScanner.java:

File file = new File(path.substring(0, slashIndex) + ".nomedia");
if (file.exists()) {
   // we have a .nomedia in one of the parent directories
   return true;
}

它没有出现在系统的图库或视频应用程序中的原因可能是因为扫描崩溃(如日志中所示)。

但是,我对媒体扫描仪也有不好的感觉。例如,为什么它不以更直接的方式停止扫描。例如,在 MediaScanner.java 中,而不是

public void scanDirectories(String[] directories, String volumeName) {
        [...]
        for (int i = 0; i < directories.length; i++) {
            processDirectory(directories[i], mClient);
        }

它可能是

public void scanDirectories(String[] directories, String volumeName) {
        [...]
        for (int i = 0; i < directories.length; i++) {
            if (! isNoMediaPath(directories[i]))
                processDirectory(directories[i], mClient);
        }

但相反,它一次又一次地在 java 代码和 cpp 代码之间来回走动。这是什么原因?

于 2013-02-17T21:15:20.177 回答
0

看起来“.nomedia”确实不会产生某些人预期的效果的一半。在 MediaScanner.java 中进一步调查后,我会说,这个文件根本不会阻止 MediaScanner 扫描整个树。它仍然为每个文件添加条目到 MediaStore,不管 noMedia 是否设置。

它只是将 MediaStore 中的那些条目标记为“不得显示”。在每个文件上,它都有一个“beginFile”和一个“endFile”。在 endFile 中,它总是以一种或另一种方式执行 mMediaInserter.insert。

令我非常困扰的是这样一个事实,它扫描了所有文件,例如一个已安装的棒,因此冒着陷入病毒的风险(专门为该扫描过程设计)并且没有 .nomedia 文件可以阻止它这样做。

于 2013-02-18T21:47:11.620 回答