Без исключения создание файлов не удается

Я пытаюсь создать пустой файл в приложении для Android. Мой код отлично работает на Android 5, но когда я тестировал Android 7 или выше, он терпит неудачу без вывода исключения.

Мой код:

downloadLocation = new File(Environment.getExternalStorageDirectory() + "/" + "folder" + System.currentTimeMillis());
downloadLocation.mkdir();

downloadFile = new File(downloadLocation, "file" + System.currentTimeMillis());
downloadFile.createNewFile();

Обратите внимание, я объявил переменные и все такое, я просто не включил это. Обе переменные downloadLocation и downloadFile имеют тип файла.

На физическом устройстве Android 5, которое я использовал, он работал нормально. Затем я протестировал виртуальное устройство Android 7, но оно не прошло без вывода ошибки в журнал. Проблема связана со вторым блоком кода, а именно с последней строкой. Я знаю это, потому что я поместил журнал между каждой строкой и каждым выводом журнала, кроме журнала после создания файла.

Очень сложно что-то отладить, когда ошибка не отображается, несмотря на наличие ошибки перехвата, которая предполагает печать трассировки стека и исключения.

Любые идеи?

В качестве примечания я знаю, что файл и папка еще не существуют, потому что я добавил отметку времени к имени, чтобы предотвратить это в целях тестирования, так как я на 100% знаю, что файл будет иметь уникальное имя в выпуске. . Вот почему я не заключил каждый блок в оператор if, который проверял бы, что файл / папка еще не существует.

разрешения во время выполнения

Pavneet_Singh 13.10.2018 06:47

так что вы видите на logcat? Ничего? или хотя бы что-то вроде "process xxxx died" или подобного?

pskink 13.10.2018 06:53

@pskink Ничего (кроме текстовых строк ручной отладки, которые я вставил сам). Приложение не аварийно завершает работу, потому что создание файла выполняется с помощью оператора try / catch, который должен печатать исключение в logcat, но этого не происходит, несмотря на то, что код catch запускается и выполняется.

TheAndroidProgrammer 13.10.2018 06:58

@Pavneet_Singh Что ты имеешь в виду? Требуются ли для Android 7 и выше более высокие разрешения? Некоторое время назад я видел, что Android 7 изменил принцип работы совместного использования файлов, но я думал, что это происходит только при доступе к файлу после создания и только при совместном использовании файла между другим приложением или другим потоком.

TheAndroidProgrammer 13.10.2018 07:00

Попробуйте добавить точки останова и подключить отладчик, чтобы вы могли точно видеть, что происходит и что происходит на каждом этапе. Вы собираетесь использовать этот каталог только для своего приложения в частном порядке? Вместо этого вы можете изменить его на getExternalFilesDir, и вам не нужно будет запрашивать разрешения на запись

Programmer001 13.10.2018 07:03

так что опубликуйте весь текущий код (с try / catch)

pskink 13.10.2018 07:03

@pskink это просто стандартный try { CODE } catch (Exception e) { e.printStackTrace(); }. Я добавил строку ручной отладки в блок catch (чтобы убедиться, что блок catch выполняется), и он запускается, хотя printStackTrace на самом деле ничего не печатает.

TheAndroidProgrammer 13.10.2018 07:06

большинству требуется разрешение времени выполнения выше 6.0, поэтому разрешение дает время выполнения, которое решит ваша проблема.

Bhuvaneshwaran Vellingiri 13.10.2018 07:10

@TheAndroidProgrammer после Android 6.0 вам необходимо реализовать проверку времени выполнения для критических разрешений, в вашем случае это READ_EXTERNAL_STORAGE, обратитесь к это

V-rund Puro-hit 13.10.2018 07:11

@ V-rundPuro-hit Вы имеете в виду, как написано на этой странице документации? developer.android.com/training/permissions/requesting

TheAndroidProgrammer 13.10.2018 07:15

@TheAndroidProgrammer да Ровно

V-rund Puro-hit 13.10.2018 07:16

так что вы увидите, если позвоните в Log.d(TAG, "inside catch block", e);? или хотя бы Log.d(TAG, "inside catch block: " + e.getMessage());?

pskink 13.10.2018 07:18

Вероятно, вы не предоставили разрешения на выполнение

debo.stackoverflow 13.10.2018 08:17

Спасибо всем за помощь! Это первое приложение, которое я создал, для которого требуется опасное разрешение, поэтому я понятия не имел, что вам нужно запускать диалоговые окна разрешений вручную.

TheAndroidProgrammer 13.10.2018 20:46
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
14
86
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Ваш код, вероятно, выдает исключение, в котором не найден файл. После звонка downloadLocation.mkdir():

if (downloadLocation.exists()) { System.out.println("File Exists"); }

Вы заметите, что сообщение не печатается. Это потому, что у вас никогда не было разрешений на запись в каталог.

Добавьте в свой AndroidManifest.xml следующее:

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

Простой способ справиться с запросом разрешений - отличная библиотека: EasyPermissions

Используя EasyPermissions, ваш код может выглядеть так:

1.) Вы вызываете функцию в своей деятельности, чтобы инициировать создание файла:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    writeFiles();
}

2.) writeFiles необходимо будет обеспечить предоставление разрешений перед выполнением файловых операций:

@AfterPermissionGranted(PERMISSIONS_REQUEST_CODE)
private void writeFiles() {
    String[] permissions = {Manifest.permission.WRITE_EXTERNAL_STORAGE};
    if (EasyPermissions.hasPermissions(this, permissions)) {
        try {
            File downloadLocation = new File(Environment.getExternalStorageDirectory() + "/" + "folder" + System.currentTimeMillis());
            downloadLocation.mkdir();

            if (downloadLocation.exists()) {
                Log.i("writeFiles()", downloadLocation.getAbsolutePath());
            }

            File downloadFile = new File(downloadLocation, "file" + System.currentTimeMillis());
            downloadFile.createNewFile();
        } catch (Exception e) {
            Log.e("ERROR", e.getMessage(), e);
        }
    } else {
        // Do not have permissions, request them now
        EasyPermissions.requestPermissions(this, "Your permission rationale", PERMISSIONS_REQUEST_CODE, permissions);
    }
}

3.) Чтобы EasyPermissions снова автоматически вызывала writeFiles () после предоставления разрешений, вам необходимо добавить это переопределение:

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    // Forward results to EasyPermissions
    EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
}

Вы заметите, что PERMISSIONS_REQUEST_CODE использовался пару раз. Это просто постоянное целое число, которое вы используете для идентификации запросов разрешений, когда onRequestPermissionsResult вызывается из Activity. Это действительно может быть любое число (например, 1000), если оно уникально. Я связался с документацией EasyPermissions, в которой будет подробнее объяснено, как это работает, но это значительно упрощает обработку разрешений во время выполнения.

Редактировать: Следующие ссылки помогут подробнее узнать о запросе разрешений для ваших приложений:

Раньше, когда пользователи устанавливали ваше приложение в Play Store, им был представлен список разрешений, необходимых вашему приложению. Если пользователь продолжил установку приложения, все разрешения были предоставлены автоматически. Android 6 изменил это, и теперь пользователи получают больше контроля над тем, какие разрешения они хотят предоставить каждому приложению.

Некоторые разрешения по-прежнему не требуют утверждения пользователем, они квалифицируются как обычные разрешения. Примером может служить разрешение INTERNET. Другие разрешения, которые могут повлиять на конфиденциальность, системные данные и т. д., Считаются опасные разрешения и потребуют от пользователя предоставить их через диалоговое окно разрешений, как показано выше. Второй URL-адрес, который я опубликовал выше, покажет вам несколько таблиц с указанием того, как квалифицируется каждое разрешение.

Имейте в виду, если пользователи отказывают в разрешении и устанавливают флажок «Больше не показывать», тогда диалоговое окно больше не будет отображаться им, и им придется перейти в приложение в системных настройках и предоставить разрешение оттуда. Если вы когда-нибудь захотите помочь пользователю добраться до этого экрана, вы можете использовать следующее намерение:

Intent intent = new Intent();
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.setData(Uri.fromParts("package", getPackageName(), null));
startActivity(intent);

вы также кричите, добавьте метод onRequestPermissionsResult в свой ответ

V-rund Puro-hit 13.10.2018 07:24

Да, сейчас я собираю полный пример разрешений

Programmer001 13.10.2018 07:31

Приходилось верить, что я занимаюсь разработкой приложений для Android более двух лет и никогда раньше не работал с разрешения. Не знал, что вам нужно вручную запускать диалоговое окно разрешений. Спасибо за помощь!

TheAndroidProgrammer 13.10.2018 20:47

Всегда есть что-то новое, чему можно научиться :) Я обновлю конец своего ответа другой ссылкой, но с Android 6 и выше разрешения, помеченные как опасные, потребуют явного одобрения пользователя.

Programmer001 13.10.2018 21:06

Другие вопросы по теме