不一致的 MediaConnection 行为,某些文件未显示在 Android 文件传输中

Inconsistent MediaConnection behaviour, some files don't show in Android File Transfer

我有一个外部存储文件的目录结构。它们没有出现在 Android 文件传输应用程序中,因此我认为这是媒体扫描仪的问题。

我在基于 Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS).

的目录中使用 FileOutputStream 创建它们

我有以下方法,从 activity 调用,所以 context 是一个 activity(暂时忘记这会阻塞主线程!):

 public void scan(Context context, File base) {
        File[] files = base.listFiles();
        if (files == null) {
            return;
        } else {
            for (File file : files) {
                if (file.isFile()) {
                    String path = file.getAbsolutePath();
                    MediaScannerConnection.scanFile(context, new String[]{path}, null, null);
                    Log.e("Langstroth", path);
                } else if (file.isDirectory()) {
                    this.scan(context, file);
                }
            }
        }
    }

    public void scan(Context context) {
        this.scan(context, this.baseDir);
    }
}

日志的输出符合预期:

E/MyApp﹕ /storage/emulated/0/Documents/Langstroth/sample/5000/1430576404874.wav
E/MyApp﹕ /storage/emulated/0/Documents/Langstroth/sample/5000/1430577209491.wav

然后很多:

E/MyApp﹕ Scan completed path /storage/emulated/0/Documents/Langstroth/sample/5000/1430576404874.wav uri content://media/external/audio/media/7836
E/MyApp﹕ Scan completed path /storage/emulated/0/Documents/Langstroth/sample/5000/1430577209491.wav uri content://media/external/audio/media/7838

这证明文件存在。不过,它们不会出现在 Android 文件传输中。

奇怪的是。另一种方法:

 public void otherDemo(Context context, File baseDir) {
            String newPath = baseDir.getAbsolutePath() + "/some/random/dirs";
        Log.e("Langstroth", "New path " + newPath);

        File dir = new File(newPath);
        dir.mkdirs();

        Log.e("Langstroth", dir.exists() ? "Dir exists": "Dir does not exist");

        File f = new File(dir, "myfile.txt");

        try {
            new BufferedOutputStream(new FileOutputStream(f)).close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        Log.e("Langstroth", f.exists() ? "File exists": "File does not exist");

        MediaScannerConnection.scanFile(context, new String[]{f.getAbsolutePath()}, null, null);
    }

和日志输出:

E/MyApp﹕ New path /storage/emulated/0/Documents/Langstroth/some/random/other/dirs
E/MyApp﹕ Dir exists
E/MyApp﹕ File exists
E/MyApp﹕ File: /storage/emulated/0/Documents/Langstroth/some/random/other/dirs/myfile.txt
E/MyApp﹕ Other scan completed path /storage/emulated/0/Documents/Langstroth/some/random/other/dirs/myfile.txt uri content://media/external/file/7842

一个测试文件出现,其他的没有

证明:

其他文件在哪里?

一般来说,在让另一个进程处理文件之前,您需要确保所有字节都通过 getFD().sync() 刷新到磁盘。特别是,这似乎有助于整个媒体扫描。

the files shows up in a .listFiles(), and .exist(), and the callback for the MediaScanner says that it completed correctly. Surely an extant (if empty) file should show up?

媒体扫描仪的方式很神秘。 :-) IOW,打败了我。

请记住,这里有多个活动部件:您的应用程序、媒体扫描器、Android 上的 MTP 守护程序和您的 MTP 客户端。崩溃可能发生在任何阶段。如果您拔下并重新插入设备,现在文件显示在您的 MTP 客户端中,我的猜测是 MTP 客户端正在使用稍微陈旧的缓存。