0

I am trying to write a log file of my app to my external SD card. To figure out how to do this, I have been trying to follow the example HERE.

There is a section about 3/4 of the way down that page that says:

If none of the pre-defined sub-directory names suit your files, you can instead call getExternalFilesDir() and pass null. This returns the root directory for your app's private directory on the external storage.

My device does not have any of those pre-defined directories, and I would rather just as well save my data to the external SD card. Using the following command:

$ ADB shell
shell@android:/ $ cd /mnt
shell@android:/ $ ls -F
d ext_sdcard

You can see my external SD card. So, I created a directory on the external SD card:

shell@android:/ $ cd ext_sdcard
shell@android:/ $ mkdir MyAwesomeApplication
shell@android:/ $ ls -F
d MyAwesomeApplication

Now is when I [sort of] use the code from the Android developers site:

public File getDocumentStorageDir(String filename){
    File file = new File("/mnt/ext_sdcard/MyAwesomeApplication", filename);
    if(!file.getParentFile().mkdirs()){
        Log.i(MainActivity.class.getName(), "Directory Not Created!");
    }
    return file;
}

When I run my application, it sort of works; I immediately get this error:

E/myPackage.MainActivity: Directory Not Created!

But then it creates the log file anyway, and successfully writes the data to the file.

My issue is that it is always overwriting the log file with new data, it doesn't append, even though I am using:

public boolean isExternalStorageWritable() {
    String state = Environment.getExternalStorageState();
    if (Environment.MEDIA_MOUNTED.equals(state)) {
        return true;
    }
    return false;
}

if(isExternalStorageWritable()){
    File logfile = getDocumenetStorageDir("mylogfile.log");
    PrintWriter logFileWriter = null;
    try {
        logFileWriter = new PrintWriter(logfile);
        logFileWriter.append("stuff ...");
    } catch(FileNotFoundException fnfe){
        Log.i(MainActivity.class.getName(), fnfe.getMessage());
    } finally {
        logFileWriter.close();
    }
}

Now, when I use this command:

shell@android:/ $ cd MyAwesomeApplication
shell@android:/ $ ls -F
- mylogfile.log

I see my log file where it should be. But when I use this command:

shell@android:/ $ cat mylogfile.log
// only the very latest piece of data is here

What I am I doing incorrectly here?

Thanks

Brian
  • 1,726
  • 2
  • 24
  • 62

1 Answers1

-1

there're two parts on your question and I'll try to address them separately.

  1. Location of files

You should never hardcode file locations like you're doing (even if it's just debug logging). The location File file = new File("/mnt/ext_sdcard/MyAwesomeApplication", filename); might work for this device, but this vary on version of Android and manufacturer. You must use the appropriate getter method available to get the correct directory. On THIS LINK you can find the complete explanation, but from what I understood of your use case you want to use the following code:

public static File getLogFile(Context context) {
   File folder = getExternalFilesDir("logs");
   if(!folder.exists()) {
       folder.mkdirs();
   }
   return new File(folder, "mylogfile.log");
}
  1. Append to an existing file.

You didn't show how you're creating the PrintWriter, but I've always used the FileWriter class without any issues on appending.

Here in this question you can see about that (How to append to a text file in android?). And here some code

FileWriter f;
try {
    f = new FileWriter(getLogFile(context), true); // true is for append
    f.write(" ..logs...");
    f.flush();
} catch(Exception e) {
     .. handle exceptions
} finally {
    if(f != null) {
        f.close();
    } catch(Exception ee){
     ... exceptions might happen here too
    }
}
Community
  • 1
  • 1
Budius
  • 39,391
  • 16
  • 102
  • 144
  • Sorry, I forgot to add the line where the PrintWriter is created. I have added it in now, it is in the "try" block. As for hard coding the location, this code will only ever be used on one device. – Brian Mar 25 '16 at 15:36
  • even, if it will ever going to be used on this device, bad practice is a bad practice and it doesn't hurt to always use the "correct" code. Give a try to write your logs with the `FileWriter` instead, I've never had problems with it. – Budius Mar 25 '16 at 15:38
  • Also, I cannot figure out how to programmatically get the ext_sdcard without hardcoding it. – Brian Mar 25 '16 at 16:02
  • I've shown on my answer how to get the external storage (which should be fine). if you absolutely must have the actual SD card itself, it's just not that simple, check this question: http://stackoverflow.com/questions/11281010/how-can-i-get-external-sd-card-path-for-android-4-0 – Budius Mar 25 '16 at 16:04
  • When I use getExternalFilesDir("logs") it returns a reference to /mnt/sdcard/... and not /mnt/ext_sdcard/... – Brian Mar 25 '16 at 16:13
  • check the question I linked on my comment. The actual SD card is quite more complex and provides zero advantages. – Budius Mar 25 '16 at 16:13
  • The advantage is that it is very easy to remove the SD card from the tablet, put it into a computer and extract the data. With it being on the internal sdcard, it is much more difficult to do this. We are running a test and the logs need to be extracted for analysis often. – Brian Mar 25 '16 at 16:16