Я пытаюсь создать пустой файл в приложении для 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, который проверял бы, что файл / папка еще не существует.
так что вы видите на logcat? Ничего? или хотя бы что-то вроде "process xxxx died" или подобного?
@pskink Ничего (кроме текстовых строк ручной отладки, которые я вставил сам). Приложение не аварийно завершает работу, потому что создание файла выполняется с помощью оператора try / catch, который должен печатать исключение в logcat, но этого не происходит, несмотря на то, что код catch запускается и выполняется.
@Pavneet_Singh Что ты имеешь в виду? Требуются ли для Android 7 и выше более высокие разрешения? Некоторое время назад я видел, что Android 7 изменил принцип работы совместного использования файлов, но я думал, что это происходит только при доступе к файлу после создания и только при совместном использовании файла между другим приложением или другим потоком.
Попробуйте добавить точки останова и подключить отладчик, чтобы вы могли точно видеть, что происходит и что происходит на каждом этапе. Вы собираетесь использовать этот каталог только для своего приложения в частном порядке? Вместо этого вы можете изменить его на getExternalFilesDir, и вам не нужно будет запрашивать разрешения на запись
так что опубликуйте весь текущий код (с try / catch)
@pskink это просто стандартный try { CODE } catch (Exception e) { e.printStackTrace(); }. Я добавил строку ручной отладки в блок catch (чтобы убедиться, что блок catch выполняется), и он запускается, хотя printStackTrace на самом деле ничего не печатает.
большинству требуется разрешение времени выполнения выше 6.0, поэтому разрешение дает время выполнения, которое решит ваша проблема.
@TheAndroidProgrammer после Android 6.0 вам необходимо реализовать проверку времени выполнения для критических разрешений, в вашем случае это READ_EXTERNAL_STORAGE, обратитесь к это
@ V-rundPuro-hit Вы имеете в виду, как написано на этой странице документации? developer.android.com/training/permissions/requesting
@TheAndroidProgrammer да Ровно
так что вы увидите, если позвоните в Log.d(TAG, "inside catch block", e);? или хотя бы Log.d(TAG, "inside catch block: " + e.getMessage());?
Вероятно, вы не предоставили разрешения на выполнение
Спасибо всем за помощь! Это первое приложение, которое я создал, для которого требуется опасное разрешение, поэтому я понятия не имел, что вам нужно запускать диалоговые окна разрешений вручную.




Ваш код, вероятно, выдает исключение, в котором не найден файл. После звонка 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 в свой ответ
Да, сейчас я собираю полный пример разрешений
Приходилось верить, что я занимаюсь разработкой приложений для Android более двух лет и никогда раньше не работал с разрешения. Не знал, что вам нужно вручную запускать диалоговое окно разрешений. Спасибо за помощь!
Всегда есть что-то новое, чему можно научиться :) Я обновлю конец своего ответа другой ссылкой, но с Android 6 и выше разрешения, помеченные как опасные, потребуют явного одобрения пользователя.
разрешения во время выполнения