1
votes

When trying to create a simple .txt or .xml external file (NOT on SD card), my app is throwing a FileNotFoundException. If I let the system pick the path (returns /storage/emulated/legacy) it throws EACCES (permission denied). Same as when I set the path manually to "/android/data" (returns /storage/emulated/0/android/data) or "/download" (returns /storage/emulated/0/Download) - both throw EACCES. If I set path to "/document" it throws ENOENT (no such file or directory).

As see below in my code, I do a check before to make sure that external storage is available and not read-only.

I ran this on 2 devices, running 4.4.2 and 4.4.4 I also added "android.permission.MOUNT_UNMOUNT_FILESYSTEMS" in the manifest as suggested in SO answers to try and force the device to use it's own file system and not the PC's when running app through USB, but it seems to keep giving me a path derived from /emulated/ I try debugging from the device itself using the developer options and thus eliminating the possibility of the app accessing the PC's storage, but the debugger on the device just hangs trying to attach.

Of course I have as well: "android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="18"

This is very frustrating as there are some similar questions on SO but with very accepted answers.

public static File getExternalStorageDirectory() {
        Log.i("EXTERNAL STORAGE DIR", EXTERNAL_STORAGE_DIRECTORY.toString());
        return EXTERNAL_STORAGE_DIRECTORY;
    }

    public static final File EXTERNAL_STORAGE_DIRECTORY = getDirectory("EXTERNAL_STORAGE", "android/data");

   public static File getDirectory(String variableName, String defaultPath) {
            String path = System.getenv(variableName);
            return path == null ? new File(defaultPath) : new File(path);
    }

        public boolean isExternalStorageReadOnly() {  
              String extStorageState = Environment.getExternalStorageState();  
              if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(extStorageState)) {  
               return true;  
              }  
              return false;  
             }  

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

        public void writeToSettingsFile(String name, String value){
//          File myDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "/settings.txt");  
//          File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS), fileUrl);
//          File myDir = getDirectory("EXTERNAL_STORAGE", "android/data");
//          File myDir = getExternalStorageDirectory();
//          File myDir = new File("download");
            File myDir = new File(Environment.getExternalStorageDirectory() + "/android/data");
            if(!myDir.exists()){
                myDir.mkdirs();
            }
            try{
             String fname = "settings.txt";
             File file = new File (myDir, fname);
             FileOutputStream fOut = new FileOutputStream(file);
             Toast.makeText(context, "you made it, fOut!!!!", Toast.LENGTH_LONG).show();
             props.setProperty(name, value);     
             props.store(fOut, "Settings Properties");
//           props.storeToXML(fOut, "Settings Properties");                      
             fOut.close();

             } catch (FileNotFoundException e) {
                 e.printStackTrace();
                 Log.e("WTF", "No file found!");

             }  
             catch (IOException e) {e.printStackTrace();
             }  

            }  
2
returns /storage/emulated/0/android/data. That is a confusing path. Every device has already /storage/emulated/0/Android/data so why do you want to create a directory with A changed to a? Better have a look at getExternalFilesDir if you want to use the Android folder. - greenapps
props is a reference to java.util.Properties class that I set earlier in the code. It is a simple way to set name/value pairs, and is irrelevant to the problem. I succeeded in writing the properties to an internal file, but I need external file since it must be read/writable from sister applications. - galaxigirl

2 Answers

0
votes

I think the problem is in your this line

android:maxSdkVersion="18" .

Cause You are testing on 4.4.2. And this device has api level 19.

0
votes

Okay this is the solution :

public void writeToSettingsFile(String name, String value){
//          File myDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "/settings.txt");
//          File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS), fileUrl);
//          File myDir = getDirectory("EXTERNAL_STORAGE", "android/data");
//          File myDir = getExternalStorageDirectory();
//          File myDir = new File("download");
        File myDir = new File(this.getExternalFilesDir(null), name);
        if(!myDir.exists()){
            myDir.mkdirs();
        }
        try{
            String fname = "settings.txt";
            File file = new File (myDir, fname);
            FileOutputStream fOut = new FileOutputStream(file);

            fOut.write(value.getBytes());

//           props.storeToXML(fOut, "Settings Properties");
            fOut.close();

        } catch (FileNotFoundException e) {
            e.printStackTrace();
            Log.e("WTF", "No file found!");

        }
        catch (IOException e) {e.printStackTrace();
        }

    }

Try this method. The problem was you cant get internal directory like this

File myDir = new File(Environment.getExternalStorageDirectory() + "/android/data"); // You don't have the permission to do this 

if you want to write on internal storage you can get directory like this

File myDir = new File(this.getExternalFilesDir(null), name);

And you can take a look to For more information about saving files