ContextCompat.getExternalFilesDirs(context, null) says:
Returns absolute paths to application-specific directories on all external storage devices where the application can place persistent files it owns.
For example a Huawei Honor running Android 5.1.1 returns the following from that method:
/storage/emulated/0/Android/data/my.package.name/files
/storage/sdcard1/Android/data/my.package.name/files
The second directory is a removable sd card. However, if I attempt to read or write to that directory I get an Exception: android.system.ErrnoException: open failed: EACCES (Permission denied)
The app does have WRITE_EXTERNAL_STORAGE
. And this works just fine on a Samsung Galaxy Note 4 running Android 4.4.4. This is not related to Android 6.0's optional permissions, since this is a problem showing on 5.1.1.
The API says the application can place persistent files it owns
yet it doesn't appear to be the case.
I've heard reports from other devices as well, including more modern Samsung devices. Is this just OEMs not implementing this correctly or is there something I'm missing with Android's complicated storage frameworks?
Here is some code that will demonstrate this on this and some devices.
File removable = ContextCompat.getExternalFilesDirs(context, null)[1];
if (removable.exists() && removable.canRead() && removable.canWrite()) {
File test = new File(removable, "test");
test.createNewFile(); // Throws the exception mentioned above
}
Any attempts to create, move, mkdir files in that directory fails.
Well, I wrapped your code in this activity:
package com.commonsware.myapplication;
import android.app.Activity;
import android.os.Bundle;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import android.widget.Toast;
import java.io.File;
import java.io.IOException;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
File removable = ContextCompat.getExternalFilesDirs(this, null)[1];
if (removable.exists() && removable.canRead() && removable.canWrite()) {
File test = new File(removable, "test");
try {
test.createNewFile(); // Throws the exception mentioned above
}
catch (IOException e) {
Log.e(getClass().getSimpleName(), "Exception creating file", e);
Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG).show();
}
}
}
}
It runs fine on a Huawei Honor 5X, running Android 6.0.1:
$ adb shell ls -al /storage/1A30-3598/Android/data/com.commonsware.myapplication/files
-rwxrwx--x u0_a29 sdcard_rw 0 2017-05-03 18:02 test
So, my guess is that this is a device-specific incompatibility.
For a number of reason I would like to inquire how @CommonsWare got the code to run without a ArrayIndexOutOfBoundsException: length=1; index=1 ERROR the [0] needs to be set to [0] We have been testing this concept for sometime now to write a method that lets the user select Internal or External Storage Can someone explain how this works or why it does not work for us The above answer needs to be formatted this way
File removable = ContextCompat.getExternalFilesDirs(this,null)[0];
if (removable.exists() && removable.canRead() && removable.canWrite()) {
THE_PATH = String.valueOf(removable);
THE_PATH = THE_PATH + "/Documents/";
}else {
Toast.makeText(getApplicationContext(),"NO SD CARD",
Toast.LENGTH_LONG).show();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With