How to check permission is granted for a directory path and won't thorow EACCES error?

android, android-4.4-kitkat, permission-denied, permissions, sd-card

Solution

try {
    Process p = new ProcessBuilder("ls", "-l", "-s", dir.getCanonicalPath()).start();

    String line;
    ArrayList<String> lineOut = new ArrayList<>();

    BufferedReader error = new BufferedReader(new InputStreamReader(p.getErrorStream()));
    while ((line = error.readLine()) != null) {
        Log.e(TAG, "ls error = "+line);
    }
    error.close();

    BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
    while ((line = input.readLine()) != null) {
        lineOut.add(line);
    }

    input.close();

    String[] strings = lineOut.toArray(new String[]{});
    List<FilesLS.FileEntry> fileEntries = FilesLS.processNewLines(strings);
    for(FilesLS.FileEntry file : fileEntries){
        Log.d(TAG, file.name +" = " + file.permissions);
    }

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

And some edits to this class

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public final class FilesLS {
    /**
     * Entry type: File
     */
    public static final int TYPE_FILE = 0;
    /**
     * Entry type: Directory
     */
    public static final int TYPE_DIRECTORY = 1;
    /**
     * Entry type: Directory Link
     */
    public static final int TYPE_DIRECTORY_LINK = 2;
    /**
     * Entry type: Block
     */
    public static final int TYPE_BLOCK = 3;
    /**
     * Entry type: Character
     */
    public static final int TYPE_CHARACTER = 4;
    /**
     * Entry type: Link
     */
    public static final int TYPE_LINK = 5;
    /**
     * Entry type: Socket
     */
    public static final int TYPE_SOCKET = 6;
    /**
     * Entry type: FIFO
     */
    public static final int TYPE_FIFO = 7;
    /**
     * Entry type: Other
     */
    public static final int TYPE_OTHER = 8;
    /**
     * Device side file separator.
     */
    public static final String FILE_SEPARATOR = "/"; //$NON-NLS-1$
    /**
     * Regexp pattern to parse the result from ls.
     */
    private static Pattern sLsPattern = Pattern
        .compile("^([bcdlsp-][-r][-w][-xsS][-r][-w][-xsS][-r][-w][-xstST])\\s+(\\S+)\\s+   (\\S+)\\s+(\\d{4}-\\d\\d-\\d\\d)\\s+(\\d\\d:\\d\\d)\\s+(.*)$"); //$NON-NLS-1$  \s+([\d\s,]*)

    public static List<FileEntry> processNewLines(String[] lines) {
        List<FileEntry> listOfFiles = new ArrayList<FileEntry>();
        for (String line : lines) {
            // no need to handle empty lines.
            if (line.length() == 0) {
                continue;
            }
            // run the line through the regexp
            Matcher m = sLsPattern.matcher(line);
            if (m.matches() == false) {
                continue;
            }
            // get the name
            String name = m.group(6);
            // get the rest of the groups
            String permissions = m.group(1);
            String owner = m.group(2);
            String group = m.group(3);
            // String size = m.group(4);
            String date = m.group(4);
            String time = m.group(5);
            String info = null;
            // and the type
            int objectType = TYPE_OTHER;
            switch (permissions.charAt(0)) {
                case '-':
                    objectType = TYPE_FILE;
                    break;
                case 'b':
                    objectType = TYPE_BLOCK;
                    break;
                case 'c':
                    objectType = TYPE_CHARACTER;
                    break;
                case 'd':
                    objectType = TYPE_DIRECTORY;
                    break;
                case 'l':
                    objectType = TYPE_LINK;
                    break;
                case 's':
                    objectType = TYPE_SOCKET;
                    break;
                case 'p':
                    objectType = TYPE_FIFO;
                    break;
            }
            // now check what we may be linking to
            if (objectType == TYPE_LINK) {
                String[] segments = name.split("\\s->\\s"); //$NON-NLS-1$
                // we should have 2 segments
                if (segments.length == 2) {
                    // update the entry name to not contain the link
                    name = segments[0];
                    // and the link name
                    info = segments[1];
                    // now get the path to the link
                    String[] pathSegments = info.split(FILE_SEPARATOR);
                    if (pathSegments.length == 1) {
                        // the link is to something in the same directory,
                        // unless the link is ..
                        if ("..".equals(pathSegments[0])) { //$NON-NLS-1$
                            // set the type and we're done.
                            objectType = TYPE_DIRECTORY_LINK;
                        } else {
                            // either we found the object already
                            // or we'll find it later.
                        }
                    }
                }
                // add an arrow in front to specify it's a link.
                info = "-> " + info; //$NON-NLS-1$;
            }
            FileEntry entry = new FileEntry();
            entry.permissions = permissions;
            entry.name = name;
            // entry.size = size;
            entry.date = date;
            entry.time = time;
            entry.owner = owner;
            entry.group = group;
            if (objectType == TYPE_LINK) {
                entry.info = info;
            }
            listOfFiles.add(entry);
        }
        return listOfFiles;
    }

    public final static class FileEntry {
        String name;
        String info;
        String permissions;
        String size;
        String date;
        String time;
        String owner;
        String group;
        int type;
    }
}

Problem

I have a photo editing android app that users can choose the output directory of the the result photos. Problem is Google made a change on sdcard write permission with the KITKAT version and devices with Android KITKAT version won't allow apps to write secondary sdcards. Now I need to check if the choosen directory by user has granted the permission and won't throw EACCES error. I am already checking canRead and canWrite but these won't help. Could you please tell me how can I check if the choosen directory won't throw EACCES. My only solution is trying to write a file in a try catch, however I am hoping there is better way to do it. [update k3b 2016-09-19] i tried this on my android-4.4 but without success ``` Uri uri = Uri.fromFile(file); int permissionCode = context.checkCallingOrSelfUriPermission(uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION); if (permissionCode == PackageManager.PERMISSION_DENIED) { // on my android-4.4 i always get PERMISSION_DENIED even // if i can overwrite the file return false; } ```

Original source