How to write files to external public storage in Android so that they are visible from Windows?

My app should save files to a place where, when you connect your phone/tablet to a computer, you can see them through the system file explorer.

This is the way I implemented file writing:

protected String mDir = Environment.DIRECTORY_DOCUMENTS;
protected File mPath = Environment.getExternalStoragePublicDirectory(mDir);

protected void writeLogFile(String filename) {
    File f = new File(mPath, filename + ".txt");
    f.getParentFile().mkdirs();
    try (BufferedWriter bw = new BufferedWriter(new FileWriter(f, false))) {

        // Details omitted.

    } catch (Exception e) {
        e.printStackTrace();
        return;
    }
    makeText("Wrote " + f.getAbsolutePath());
}

This is what I see when I connect my Sony Xperia Z4 tablet to Windows (notice missing documents folder):

windows file explorer showing tablet contents

This is the directory to which the file is written (using above implementation):

android device monitor showing file system

What is wrong with my implementation?


Solution 1:

What is wrong with my implementation?

MediaStore has not discovered your newly-created files yet. What you see in Windows — and in many on-device "gallery" apps — is based on what MediaStore has indexed.

Use MediaScannerConnection and its scanFile() method to tell MediaStore about your file, once you have written out your data to disk:

public void scanFile(Context ctxt, File f, String mimeType) {
    MediaScannerConnection
        .scanFile(ctxt, new String[] {f.getAbsolutePath()},
                  new String[] {mimeType}, null);
}

or, in Kotlin:

fun scanFile(ctxt: Context, f: File, mimeType: String) {
  MediaScannerConnection.scanFile(ctxt, arrayOf(f.getAbsolutePath()), arrayOf(mimeType), null)
}