2

Writing some text to a file on an android device seems to be a major endeavor. Starting from an answer given here I have implemented the following code into my single 'Hello-World' activity:

try {
    OutputStreamWriter outputStreamWriter = new OutputStreamWriter(this.openFileOutput("config.txt", Context.MODE_PRIVATE));
    outputStreamWriter.write("lalala");
    outputStreamWriter.close();
} catch (IOException e) {
    Log.e("Exception", "File write failed: " + e.toString());
}

which does not throw an exception, but seems to work. But is there a way to 'see' the file created with the File Manager on android? The code snippet seems to write to a 'secret' location on the android file system related to the application itself (governed by using this.openFileOutput).

Consulting different google-links (this and this and this) I come up with the following code:

File file = new File(this.getExternalFilesDir("temp"), "testfile.txt");
FileOutputStream fileOutput = openFileOutput(file.getName(), Context.MODE_WORLD_WRITEABLE);
fileOutput.write("lalala");
fileOutput.close();

which throws an error

Error:(55, 19) error: no suitable method found for write(String) method FileOutputStream.write(int) is not applicable (actual argument String cannot be converted to int by method invocation conversion) method FileOutputStream.write(byte[],int,int) is not applicable (actual and formal argument lists differ in length) method OutputStream.write(int) is not applicable (actual argument String cannot be converted to int by method invocation conversion) method OutputStream.write(byte[],int,int) is not applicable (actual and formal argument lists differ in length) method OutputStream.write(byte[]) is not applicable (actual argument String cannot be converted to byte[] by method invocation conversion)

So how to do this right?

As a side note: This is for debugging/educational purposes only and not intended to be part of a final app!

To be clear: I want to create a file inside the temp directory I can see with a FileManager (the temp directory is on the same level as My Documents , Music, DCIM, Download and the like...)

Community
  • 1
  • 1
Alex
  • 41,580
  • 88
  • 260
  • 469

1 Answers1

7

But is there a way to 'see' the file created with the File Manager on android?

I am not certain what "the File Manager" is that you are referring to, as Android does not really have one. However, you are writing to an app's internal storage, and that is private to the app. It cannot be viewed by other apps or ordinary users, except on rooted devices and via some cumbersome Android SDK tools.

So how to do this right?

File file = new File(this.getExternalFilesDir(null), "testfile.txt");
FileOutputStream fileOutput = new FileOutputStream(file);
OutputStreamWriter outputStreamWriter=new OutputStreamWriter(fileOutput);
outputStreamWriter.write("lalala");
outputStreamWriter.flush();
fileOutput.getFD().sync();
outputStreamWriter.close();

Also:

  • Please do this work on a background thread

  • On Android 4.3 (API Level 18) and older devices, you need to hold the WRITE_EXTERNAL_STORAGE permission to work with external storage

If you also want to have this file show up quickly in on-device or on-development-machine file managers, use this after closing the file:

MediaScannerConnection.scanFile(
  this,
  new String[]{file.getAbsolutePath()},
  null,
  null);

(where this is some Context, such as an Activity or Service)

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • What is the unused variable `outputStreamWriter` used for? – Alex Jun 13 '16 at 19:35
  • @Alex: Whoops, sorry -- that was for the `write()` call. I have fixed my answer. – CommonsWare Jun 13 '16 at 19:36
  • Ok I see, thanks. Could you explain what the differences are between `File`, `FileOutputStream` and `OutputStreamWriter`? I am only familiar with several programming language which usually have a single entity named `File` or something to write something to a file. Why does android use these three entities instead? What is the reason for that complication? – Alex Jun 13 '16 at 19:39
  • @Alex: "Why does android use these three entities instead?" -- Android doesn't. Java does. As for "why did developer X do thing Y that I disagree with?", Stack Overflow is not well-suited for such questions. The only person who usually can answer that definitively is developer X, who is unlikely to be helping here. I can tell you that files being separate from streams is a common concept in programming languages, because streams do not have to relate to files (e.g., streams for data exchanged over sockets). – CommonsWare Jun 13 '16 at 19:43
  • Anyway, your code does not really seem to work. When I check on my device in the `temp` directory, I do not see a file named `testfile.txt`. – Alex Jun 13 '16 at 19:45
  • @Alex: Sorry, you had that there, and I copied it without thinking. `"temp"` is not a valid value. Use `null` or one of [the documented values](https://developer.android.com/reference/android/content/Context.html#getExternalFilesDir(java.lang.String)). – CommonsWare Jun 13 '16 at 19:52
  • Still does not seem to work. I tried `Environment.DIRECTORY_PICTURES` and `Environment.DIRECTORY_MUSIC`, but no file named `testfile.txt` was created in any of these directories... – Alex Jun 13 '16 at 19:58
  • @Alex: Where and how are you looking? `getExternalFilesDir()` will be in `Android/data/your.application.id.here/files/` in external storage, where `your.application.id.here` is your `applicationId` in `build.gradle` (or your `package` in `AndroidManifest.xml`). If you are using anything other than `adb shell` to look, you also need to use the `MediaScannerConnection` code that I mentioned, and possibly click "refresh" or "reload" in the file manager. – CommonsWare Jun 13 '16 at 20:02
  • Ok, now I have it! Thanks. I need to write down that 'external files dir' is bound to the application in that very special app dir... Never seen it explained in any of these links I have linked... – Alex Jun 13 '16 at 20:04
  • @Alex: Presumably, you were previously looking in top-level directories in external storage. Standard ones (e.g., `DIRECTORY_MUSIC`) are obtained via `Environment.getExternalStoragePublicDirectory()`. – CommonsWare Jun 13 '16 at 20:13