1

My device is Android 6.0.1 operating system, but cannot write file to external SD card, from the log, there is no authority, but I have the right to apply for success, and that the permissions in the AndroidManifest.xml file;

I use the "adb shell dumpsys package packagename" command, read and write permissions are returned to the true; Then I looked at the Settings-> Apps->My Application - > Permissions, read and write permissions have been granted;

I must use an external SD card

Has anyone encountered this problem, I think this is very strange

private void requestPermiss() {
    if (ContextCompat.checkSelfPermission(this, Manifest.permission_group.STORAGE) != PackageManager.PERMISSION_GRANTED) {
        if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.READ_EXTERNAL_STORAGE)) {
            Toast.makeText(this, "We need to read file from sdcard", Toast.LENGTH_SHORT).show();
            ActivityCompat.requestPermissions(this, new String[]{
                    Manifest.permission.READ_EXTERNAL_STORAGE,
                    Manifest.permission.WRITE_EXTERNAL_STORAGE,
            }, 0);
        }

    }
}

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if(requestCode == 0){
        if(grantResults[0] == PackageManager.PERMISSION_GRANTED
                && grantResults[1] == PackageManager.PERMISSION_GRANTED){
            writeFile();
        }
    }
}

private void writeFile(){
    new Thread(new Runnable() {
        @Override
        public void run() {
            String sdDir = getPath_For23(MainActivity.this, 0);
            File file = new File(sdDir + "/test.txt");
            if(!file.exists()){
                try {
                    file.createNewFile();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }).start();
}

private static String getPath_For23(Context context, int flag) {
    try {
        StorageManager sManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
        Class class_StorageManager = StorageManager.class;
        Method method_getVolumes = class_StorageManager.getMethod("getVolumes");

        Class<?> class_VolumeInfo = Class.forName("android.os.storage.VolumeInfo");
        Method method_getPath = class_VolumeInfo.getMethod("getPath");
        Method method_getDisk = class_VolumeInfo.getMethod("getDisk");

        Class<?> class_DiskInfo = Class.forName("android.os.storage.DiskInfo");
        Method method_isSd = class_DiskInfo.getMethod("isSd");
        Method method_isUsb = class_DiskInfo.getMethod("isUsb");

        List<Object> volumes = (List<Object>) method_getVolumes.invoke(sManager);
        for (Object volumeInfo : volumes) {
            File file = (File) method_getPath.invoke(volumeInfo);
            if (file != null) {
                Object diskInfo = method_getDisk.invoke(volumeInfo);
                if (diskInfo != null) {
                    boolean isSd = (boolean) method_isSd.invoke(diskInfo);
                    boolean isUsb = (boolean) method_isUsb.invoke(diskInfo);
                    switch (flag){
                        case 0:
                            if (isSd) {
                                return  file.getAbsolutePath();
                            }
                            break;
                        case 1:
                            if (isUsb) {
                                return file.getAbsolutePath();
                            }
                            break;
                    }
                }
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}
 }

Error log:

W/System.err: java.io.IOException: open failed: EACCES (Permission denied)

W/System.err: at java.io.File.createNewFile(File.java:939)

W/System.err: at com.example.user.test60.MainActivity$1.run(MainActivity.java:70)

W/System.err: at java.lang.Thread.run(Thread.java:818)

W/System.err: Caused by: android.system.ErrnoException: open failed: EACCES (Permission denied)

W/System.err: at libcore.io.Posix.open(Native Method)

W/System.err: at libcore.io.BlockGuardOs.open(BlockGuardOs.java:186)

W/System.err: at java.io.File.createNewFile(File.java:932)

W/System.err: ... 2 more

Victor
  • 11
  • 7
  • try Environment.getExternalStorageDirectory(); to get the path.. – Martin Pfeffer Mar 20 '17 at 02:48
  • 1
    It will return /storage/emulated/0, this internal sdcard path , not external sdcard – Victor Mar 20 '17 at 03:10
  • Ok, are you sure the correct permissions are set? You check only READ... to show the permissions set http://stackoverflow.com/questions/21091022/listing-permissions-of-android-application-via-adb do you really need the sdcard? Google recommends the internal storage to use (faster, more secure, you can rely on...) – Martin Pfeffer Mar 20 '17 at 03:40
  • I have checked WRITE.... , and use dumpsys package packagename, it return granted=true both read and write permission. – Victor Mar 20 '17 at 06:41
  • weird. the exception is raised in main line 70. this is where you call the new file, isn't it? – Martin Pfeffer Mar 20 '17 at 06:48
  • Please tell the exact path for your sd card. – greenapps Mar 20 '17 at 07:51

4 Answers4

0

Try this

String imgLocation = Environment.getExternalStorageDirectory().toString() + "/FolderName/", fileName;
                FileOutputStream fOut = null;
                Date date = new Date();
                File dir = new File(imgLocation);
                if (!dir.exists()) {
                    dir.mkdirs();
                }
                fileName = "img" + date.getTime() + ".jpg";
                file = new File(dir, fileName);
                try {
                    Bitmap imageBitmap = bm;
                    FileOutputStream out = new FileOutputStream(file);
                    imageBitmap.compress(Bitmap.CompressFormat.JPEG, 85, out);
                    out.flush();
                    out.close();
                   } catch (FileNotFoundException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
0

Heads up, getExternalFilesDirectory() != getExternalFilesDirs()

I am quite sure that getExternalFilesDirs(String) will do the job. check https://developer.android.com/reference/android/os/Environment.html

they say:

In devices with multiple shared/external storage directories, this directory represents the primary storage that the user will interact with. Access to secondary storage is available throughgetExternalFilesDirs(String),getExternalCacheDirs(), and getExternalMediaDirs()

Martin Pfeffer
  • 12,471
  • 9
  • 59
  • 68
  • Yes, these methods can really return to the external SD card directory, but can only get to the application directory, but if my file on the SD card root directory, this method is not accessible – Victor Mar 20 '17 at 07:49
0

An SD card on modern Android versions like 6.0 is read only.

The only place where your app can write is in a app specific directory on it.

Look at the second item returned by getExternalFilesDirs() for that path.

greenapps
  • 11,154
  • 2
  • 16
  • 19
  • I've tried it, and it's internal sdcrad, it can only get the directory of the specified type – Victor Mar 21 '17 at 10:16
  • +Victor, use getExternalFilesDirS() and not getExternalFilesDir()...the first one returns an array..please check the value at index 1, it should be the SD card – Alexandru Circus Apr 29 '17 at 10:05
0

Try adding this to your Manifest file:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

This will get needed permissions.

Excalibur
  • 151
  • 3
  • 9