Как проверить разрешение предоставлено для пути к каталогу и не будет обрабатывать ошибку EACCES?

У меня есть приложение для редактирования фотографий для Android, которое позволяет выбрать выходной каталог результатов. Проблема заключается в том, что Google внес изменения в разрешение на запись SDK с версией KITKAT, а устройства с версией Android KITKAT не позволят приложениям записывать вторичные SD-карты. Теперь мне нужно проверить, предоставил ли выбранный каталог пользователю разрешение и не выбросит ошибку EACCES. Я уже проверяю canRead и canWrite, но это не поможет. Не могли бы вы рассказать мне, как я могу проверить, не выбрасывает ли выбранный каталог EACCES. Мое единственное решение пытается написать файл в try catch, однако я надеюсь, что есть лучший способ сделать это.

[Обновление k3b 2016-09-19]

Я попробовал это на своем Android-4.4, но без успеха

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; } 

Solutions Collecting From Web of "Как проверить разрешение предоставлено для пути к каталогу и не будет обрабатывать ошибку EACCES?"

 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(); } 

И некоторые отредактировали этот класс

 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; } } 

Добавьте в массив, какие разрешения вам нужны: private static final int REQUEST_CODE_PERMISSION = 2; Строка [] mPermission = {Manifest.permission.INTERNET, Manifest.permission.CHANGE_WIFI_STATE, Manifest.permission.CHANGE_NETWORK_STATE, Manifest.permission.ACCESS_WIFI_STATE};

Добавьте это в onCreate или где вы хотите:

  try { if (ActivityCompat.checkSelfPermission(this, mPermission[0]) != MockPackageManager.PERMISSION_GRANTED || ActivityCompat.checkSelfPermission(this, mPermission[1]) != MockPackageManager.PERMISSION_GRANTED || ActivityCompat.checkSelfPermission(this, mPermission[2]) != MockPackageManager.PERMISSION_GRANTED || ActivityCompat.checkSelfPermission(this, mPermission[3]) != MockPackageManager.PERMISSION_GRANTED) { Log.e("TAGTAG", "DENIED"); ActivityCompat.requestPermissions(this, mPermission, REQUEST_CODE_PERMISSION); // If any permission aboe not allowed by user, this condition will execute every tim, else your else part will work } else { Log.e("TAGTAG", "GRANTED"); } } catch (Exception e) { e.printStackTrace(); } 

`Declare использует разрешения в Manifest.xml