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 (またはその他のもの) は、「保留中」フォルダー内の完成したファイルをスキャンし、システム ログに barfs しようとします。

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ファイルの存在を通知しましたが、エラーメッセージが残ります。

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 によるツリー全体のスキャンをまったく停止しないと言えます。noMedia が設定されているかどうかに関係なく、各ファイルの MediaStore にエントリを追加します。

MediaStore 内のこれらのエントリを「表示してはならない」とマークするだけです。各ファイルで、「beginFile」と「endFile」を実行します。endFile では、常に何らかの方法で mMediaInserter.insert を実行します。

これについて非常に気になるのは、マウントされたスティックなどのすべてのファイルをスキャンするため、ウイルス (そのスキャンプロセス用に特別に設計されたもの) にトラップされるリスクがあり、.nomedia ファイルでそれを止めることができないという事実です。そうする。

于 2013-02-18T21:47:11.620 に答える