Android: не удалось установить каталог

Я использовал "Environment.getExternalStorage()" для хранения и управления файлами. И с этим методом нет предупреждающего сообщения от logcat и работает очень хорошо.

Но мой проект должен использовать метод "Context.getExternalFilesDir(String type)", и есть предупреждающее сообщение

ContextImpl: Не удалось обеспечить каталог:/storage/external_SD/Android/data/(имя пакета)/файлы

К счастью, файл File работает нормально (чтение или запись или создание папки тоже работает).

Но я хочу знать, как разрешить это предупреждение. Я что-то пропустил?

Ответ 1

Вы должны знать, как появляется предупреждающее сообщение.

getExternalFilesDir(String type) вызовет getExternalFilesDirs(String type) (обратите внимание на 's' в конце второго имени метода).

getExternalFilesDirs(String type) найдет все типы этого типа и вызовет ensureDirsExistOrFilter() в конце, чтобы гарантировать существование каталогов.

Если каталог недоступен, он выведет предупреждение!

Log.w(TAG, "Failed to ensure directory: " + dir);
dir = null;

Итак, если ваше устройство имеет два пути sdcard, оно будет создавать два каталога. Если он недоступен, появится предупреждение.

Вывод заключается в том, что предупреждение не нужно исправлять.

Ответ 2

Если у вас есть код, который выполняет итерацию файлов, вызывая этот API много раз, это предупреждение может вызвать загрязнение журналов. Чтобы решить эту проблему (поскольку предупреждение действительно доброкачественное), вы можете создать класс-оболочку, который сохраняет результат вызова getExternalFilesDir/getExternalCacheDir и впоследствии возвращает сохраненное значение вместо вызова API. Таким образом, по крайней мере, вы только когда-нибудь увидите это сообщение.

Ответ 3

Я следую за источником getExternalFilesDir()

/**
 * Ensure that given directories exist, trying to create them if missing. If
 * unable to create, they are filtered by replacing with {@code null}.
 */
private File[] ensureExternalDirsExistOrFilter(File[] dirs) {
    File[] result = new File[dirs.length];
    for (int i = 0; i < dirs.length; i++) {
        File dir = dirs[i];
        if (!dir.exists()) {
            if (!dir.mkdirs()) {
                // recheck existence in case of cross-process race
                if (!dir.exists()) {
                    // Failing to mkdir() may be okay, since we might not have
                    // enough permissions; ask vold to create on our behalf.
                    final IMountService mount = IMountService.Stub.asInterface(
                            ServiceManager.getService("mount"));
                    try {
                        final int res = mount.mkdirs(getPackageName(), dir.getAbsolutePath());
                        if (res != 0) {
                            Log.w(TAG, "Failed to ensure " + dir + ": " + res);
                            dir = null;
                        }
                    } catch (Exception e) {
                        Log.w(TAG, "Failed to ensure " + dir + ": " + e);
                        dir = null;
                    }
                }
            }
        }
        result[i] = dir;
    }
    return result;
}


немедленное использование Environment.getExternalStorageDirectory() получить ExternalDirs

public final class StorageUtil {

public static final String DIR_ANDROID = "Android";
private static final String DIR_DATA = "data";
private static final String DIR_FILES = "files";
private static final String DIR_CACHE = "cache";

@Nullable
public static synchronized File getExternalStorageAppFilesFile(Context context, String fileName) {
    if (context == null) return null;
    if (fileName == null) return null;
    if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
        File dirs = buildExternalStorageAppFilesDirs(Environment.getExternalStorageDirectory().getAbsolutePath(), context.getPackageName());
        return new File(dirs, fileName);
    }
    return null;
}


public synchronized static File buildExternalStorageAppFilesDirs(String externalStoragePath, String packageName) {
    return buildPath(externalStoragePath, DIR_ANDROID, DIR_DATA, packageName, DIR_FILES);
}


public synchronized static File buildPath(String base, String... segments) {
    File cur = new File(base);
    for (String segment : segments) {
        cur = new File(cur, segment);
    }
    return cur;
}

}