Android studio удалить файл
Сегодня я бы хотел рассказать вам о правильной работе с файлами в ОС Android. Итак, чаще всего у новичков возникают ситуации, когда обычные Java функции не могут корректно создать тот или иной файл в системе Android.
Во-первых, вам нужно обратить внимание на интересную особенность ОС:
когда вы устанавливаете apk приложение в эмулятор или телефон, система Linux (на которой базируется ядро Android) выделяет ему специальный User-ID, который является неким ключом доступа к (sandbox). То есть другие приложения в телефоне не смогут получить доступ к чтению файлов вашего приложения просто так. Кончено, всё это сделано в целях безопасности.
В общем, если вы запустите следующий код:
FileWriter f = new FileWriter("impossible.txt");
То этот код вызовет исключение: ‘java.io.FileNotFoundException: /impossible.txt ‘
Тогда как должен в случае отсутствия файла создать его.
Далее стоит отметить, что данное ограничение не распространяется на файлы, записываемые на SDCard. Туда можно писать любые файлы без всяких проблем, правда предварительно нужно добавить в AndroidManifest разрешение на запись:
Код файла на карту:
File fileName = null;
String sdState = android.os.Environment.getExternalStorageState();
if (sdState.equals(android.os.Environment.MEDIA_MOUNTED)) File sdDir = android.os.Environment.getExternalStorageDirectory();
fileName = new File(sdDir, "cache/primer.txt");
> else fileName = context.getCacheDir();
>
if (!fileName.exists())
fileName.mkdirs();
try FileWriter f = new FileWriter(fileName);
f.write("hello world");
f.flush();
f.close();
> catch (Exception e)
>
Как уже ранее было сказано мною, android приложение находится в некой песочнице, изолированной от воздействия со стороны других приложений по умолчанию. Для того, чтобы создать файл внутри этой песочницы, следует использовать функцию openFileOutput(). Хочу отметить 2 аргумента:
1. имя файла
2. режим доступа к нему со стороны чужих приложений
С первым аргументом все ясно, что касается второго, то режимов существует два: MODE_WORLD_READABLE и/или MODE_WORLD_WRITEABLE.
И ещё, чтобы записать файл можно использовать следующий код:
final String TESTSTRING = new String("Hello Android");
FileOutputStream fOut = openFileOutput("samplefile.txt", MODE_WORLD_READABLE);
OutputStreamWriter osw = new OutputStreamWriter(fOut);
// записываем строку в файл
osw.write(TESTSTRING);
/* проверяем, что все действительно записалось и закрываем файл */
osw.flush();
osw.close();
Для чтения файлов используется метод openFileInput():
FileInputStream fIn = openFileInput("samplefile.txt");
InputStreamReader isr = new InputStreamReader(fIn);
char[] inputBuffer = new char[TESTSTRING.length()];
isr.read(inputBuffer);
String readString = new String(inputBuffer);
Для удаления используется метод deleteFile() в контексте приложения/активити. На этом я бы хотел закончить полезный пост, спасибо за внимание!
Теперь единственная проблема заключается в том, что имя пути, которое я получаю, это «content: // downloads / all_downloads / 644», и, согласно моему распечатанному logcat, этот файл не может быть найден. Примечание. Этот файл действительно существует, и я использовал тот же uri для воспроизведения видео. Спасибо за помощь. РЕДАКТИРОВАТЬ: ОК. Вот как я получил свой URI.
Я очень признателен за приведенные ниже предложения, но я все еще застрял даже после прочтения документации. Предположим, я не могу удалить с помощью URI, есть ли способ вместо этого преобразовать мой URI во что-то полезное. Я не хочу вручную вводить адрес расположения моих файлов.
@ Вот мой весь код .
Public class Cacher
2 ответа
Итак, вот решение моей проблемы для тех, кто не хочет читать наши комментарии. Сначала выберите каталог для загрузки. Затем используйте этот путь к файлам и используйте функцию delete (). Имейте в виду, что после создания каталога с именем папки вам нужно будет ссылаться только на имя папки, а не на весь путь. Вот код, который, я надеюсь, поможет:
// Где я создаю каталог
Я просмотрел примеры других людей и реализовал это.
Это будет работать только в том случае, если Uri имеет схему file и у вас есть права на запись в каталог, содержащий файл.
Как удалить файл из внешнего хранилища android studio, используя только URI
Скорее всего, нет.
Если вы получаете Uri от ACTION_OPEN_DOCUMENT или ACTION_CREATE_DOCUMENT , оберните Uri в DocumentFile , используя fromSingleUri() , затем вызовите delete() на DocumentFile .
Для любого другого content Uri вы можете попробовать вызвать delete() на ContentResolver , но не ожидайте, что это сработает. Не требуется, чтобы ContentProvider предлагал вам какой-либо способ удаления части контента. Приложение, поставляющее ContentProvider , должно иметь собственный способ разрешать пользователям удалять вещи.
Работа с файлами в Android не сильно отличается от таковой в Java. В этом уроке рассмотрим, как записать/прочесть файл во внутреннюю память и на SD-карту.
Project name: P0751_Files
Build Target: Android 2.3.3
Application name: Files
Package name: ru.startandroid.develop.p0751files
Create Activity: MainActivity
Заполним strings.xml:
Рисуем экран main.xml:
4 кнопки, смысл которых понятен по тексту на них.
MainActivity.java:
В onclick обрабатываем нажатия 4-х кнопок и вызываем соответствующие методы.
writeFile – запись файла во внутреннюю память. Используется метод openFileOutput, который на вход берет имя файла и режим записи: MODE_PRIVATE – файл доступен только этому приложению, MODE_WORLD_READABLE – файл доступен для чтения всем, MODE_WORLD_WRITEABLE - файл доступен для записи всем, MODE_APPEND – файл будет дописан, а не начат заново.
readFile – чтение файла из внутренней памяти. Используем метод openFileInput, принимающий на вход имя файла. Здесь и в методе записи внутреннего файла вы можете задать только имя файла, а каталог для ваших файлов вам уже выделен.
writeFileSD – запись файла на SD. Используем метод getExternalStorageState для получения состояния SD-карты. Здесь можно посмотреть какие бывают состояния. Нам нужно MEDIA_MOUNTED – когда SD-карта вставлена и готова к работе. Далее мы получаем путь к SD-карте (метод getExternalStorageDirectory), добавляем свой каталог и имя файла, создаем каталог и пишем данные в файл.
readFileSD – чтение файла с SD. Все аналогично предыдущему методу, только файл не пишем, а читаем.
Осталось в манифест добавить разрешение на работу с файлами на SD - android.permission.WRITE_EXTERNAL_STORAGE.
Все сохраним и запустим. Видим экран с 4-мя кнопками:
Внутренняя память
Жмем кнопку Записать файл. Видим в логе:
Проверим. Идем в File Explorer (Window > Show View > Other > Android > File Explorer) и открываем там папку data/data/ru.startandroid.develop.p0751files/files и видим там наш файл file.
Возвращаемся в эмулятор. Жмем Прочесть файл и в логе видим:
Это тот текст, который мы записывали в файл.
SD карта
Теперь жмем Записать файл на SD.
Файл записан на SD: /mnt/sdcard/MyFiles/fileSD
Проверяем. Идем в FileExplorer и открываем там папку mnt/sdcard/MyFiles/ а в ней файл fileSD.
Возвращаемся в эмулятор и жмем кнопку Прочесть файл с SD. В логе видим:
Содержимое файла на SD
Этот текст мы и записывали.
mnt/sdcard - обычно этот путь ведет к содержимому SD-карты. Возможно у вас он будет другой.
В общем, при работе с файлами на SD вы используете стандартные java механизмы. А при работе с внутренним хранилищем для удобства можно использовать методы-оболочки от Activity:
openFileOutput – открыть файл на запись
openFileInput – открыть файл на чтение
И есть метод getFilesDir – возвращает объект File, соответствующий каталогу для файлов вашей программы. Используйте его, чтобы работать напрямую, без методов-оболочек.
Подробности работы в java с файловой системой я здесь описывать не буду. На нашем форуме пользователь SKR сделал отличную памятку по работе с файлами. Скорее всего, вы найдете там все что нужно.
Если у вас проверка SD-карты показывает, что карта недоступна (см. лог), то убедитесь в свойствах AVD, что у вас для SDCard указан Size или File. Если указаны, то попробуйте перезапустить AVD.
На следующем уроке:
- создаем экран с вкладками
- используем иконку в названии вкладки
- используем обработчик перехода между вкладками
- в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Kotlin, RxJava, Dagger, Тестирование
- ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня
- новый чат Performance для обсуждения проблем производительности и для ваших пожеланий по содержанию курса по этой теме
Android использует файловую систему, которая аналогична дисковым файловым системам на других платформах. Эта лекция описывает, как работать с файловой системой Android для чтения и записи файлов с помощью File API (перевод документации [1]).
Объект File подходит для чтения или записи больших объемов данных в порядке от начала до конца, без пропусков. Например, это хорошо подходит для файлов картинок или для различных обменов данными через сеть. Здесь будет показано, как выполнять базовые файловые операции в Вашем приложении. Подразумевается, что Вы знакомы с файловой системой Linux и стандартной системой ввода/вывода файлов в (standard file input/output API) в java.io.
[Выбор между внутренним и внешним хранилищем (Internal Storage, External Storage)]
Все устройства Android имеют две области хранения файлов (file storage area): "internal" и "external" storage. Эти имена появились на первых стадиях развития Android, когда большинство устройств поставлялись со встроенной энергонезависимой памятью FLASH (internal storage) плюс извлекаемый носитель памяти, такой как micro SD card (external storage). Некоторые устройства делили постоянную область хранения (permanent storage space) на разделы "internal" и "external", так что даже без наличия внешнего извлекаемого хранилища (removable storage medium) всегда имеется 2 пространства хранения, и поведение API всегда одинаково - независимо от того, есть в наличии внешнее хранилище или нет. Следующие списки подводят общую черту под фактическими различиями каждого пространства хранения.
Совет: несмотря на то, что приложения по умолчанию устанавливаются в internal storage, Вы можете указать атрибут android:installLocation в файле манифеста, после чего Ваше приложение может быть установлено и на external storage. Пользователи ценят эту опцию, когда размер APK очень велик, и размер external storage space больше, чем internal storage. Дополнительную информацию см. в документации App Install Location [2].
[Получение разрешения для приложения на доступ к External Storage]
Чтобы иметь возможность записи в external storage, Вы должны запросить в файле манифеста разрешение WRITE_EXTERNAL_STORAGE :
Внимание: в настоящее время приложения имеют возможность чтения external storage без специального на то разрешения. Однако это изменится в будущих релизах системы Android. Если Ваше приложение требует чтения external storage (но не записывает в него), то Вам нужно декларировать разрешение READ_EXTERNAL_STORAGE . Чтобы обеспечить будущую работу Вашего приложения так, как это ожидалось, Вы должны декларировать это разрешение уже сейчас, до того как изменения вступят в реальную силу.
Но если Ваше приложение использует разрешение WRITE_EXTERNAL_STORAGE, то это неявно дает ему также разрешение использовать и чтение external storage.
Вам не нужно получать никаких разрешений на сохранение файлов в internal storage. Ваше приложение всегда имеет разрешение на чтение и запись файлов в свой внутренний каталог на internal storage.
[Сохранение файла в Internal Storage]
Когда сохраняется файл в internal storage, Вы можете запросить подходящую директорию для объекта файла File вызовом одного из двух методов:
getFilesDir() возвращает объект File, представляющий внутренний каталог Вашего приложения.
getCacheDir() возвращает объект File, представляющий внутренний каталог временных файлов кэша Вашего приложения. Обязательно удаляйте оттуда каждый файл, когда он больше не нужен, и реализуйте разумный предел размера для объема памяти, который используете в любой момент времени, такой как предел в 1 мегабайт. Если система Android обнаружит, что на внутреннем хранилище недостаточно места, то она может удалить Ваши файлы кэша без предупреждения.
Чтобы создать новый файл в одной из этих директорий, Вы можете использовать конструктор File(), передав ему File, предоставленный одним из этих методов, которые укажут каталог на internal storage. Пример:
Альтернативно Вы можете вызвать openFileOutput(), чтобы получить FileOutputStream, который записывает файл в Вашей внутренней директории. Например, здесь показано, как записать некий текст в файл:
Или, если Вам нужно кэшировать некоторые файлы, Вы должны вместо этого использовать createTempFile() . Например, следующий метод вытаскивает имя файла из URL и создает файл с таким именем во внутренней директории для кэша Вашего приложения:
Примечание: каталог internal storage Вашего приложения указывается на основе имени пакета приложения в специальном месте файловой системы Android. Технически другое приложение может прочитать Ваши внутренние файлы, если Вы установите файловый режим с разрешенным чтением. Однако для этого другое приложение должно также знать имя пакета Вашего приложения и имена используемых Вашим приложением файлов. Другие приложения не могут просматривать Ваши внутренние директории, и не могут получить доступ на чтение или запись, за исключением случая, когда Вы явно установите файл как читаемый и/или записываемый. Таким образом, пока Вы используете MODE_PRIVATE для Ваших файлов на internal storage, то они никогда не будут доступны для других приложений.
[Сохранение файла в External Storage]
Поскольку external storage иногда может быть недоступно (когда пользователь смонтировал его как внешний USB-носитель на PC, или когда вытащил карту SD из телефона), то перед доступом к тому Вы должны всегда проверить, что он есть в наличии. Вы можете запросить состояние external storage вызовом getExternalStorageState() . Если возвращенное состояние External Storage равно MEDIA_MOUNTED , то Вы можете читать и записывать на него свои файлы. Например, следующие методы полезны для определения доступности устройства хранения:
Несмотря на то, что external storage может быть модифицировано пользователем и другими приложениями, есть две категории файлов, которые могут быть сохранены здесь:
Публичные файлы (Public files) - это файлы, которые должны быть свободно доступны для других приложений и пользователя. Когда пользователь деинсталлирует Ваше приложение, эти файлы должны остаться доступными для пользователя. Например, такими файлами могут быть фотографии, созданные другими приложениями или другие файлы, загруженные через сеть.
Частные файлы (Private files) - это файлы, полные права на которые принадлежат Вашему приложению, и которые должны быть удалены при деинсталляции Вашего приложения пользователем. Несмотря на то, что эти файлы технически доступны для пользователя и других приложений, поскольку они находятся на внешнем извлекаемом хранилище (external storage), эти файлы не имеют в реальности особого значения для пользователя вне Вашего приложения. Когда пользователь деинсталлирует Ваше приложение, система удалит все файлы в Вашем частном каталоге на внешнем хранилище. Примером таких файлов могут быть дополнительные ресурсы, загруженные Вашим приложением или временные медиафайлы.
Если Вы хотите сохранить public-файлы на external storage, используйте метод getExternalStoragePublicDirectory() для получения экземпляра File , предоставляющего подходящую директорию на external storage. Метод принимает аргумент, указывающий тип файла, который Вы хотите сохранить, так чтобы типы файла были логически организованы с другими public-файлами, такими как DIRECTORY_MUSIC или DIRECTORY_PICTURES . Пример:
Если Вы хотите сохранить файлы, которые являются частными (private) для Вашего приложения, Вы можете получить подходящую директорию вызовом метода getExternalFilesDir() и передачей ему имени, указывающего тип директории, который Вам нужен. Каждая директория, созданная таким способом, будет добавлена к родительской директории, в которой инкапсулированы все файлы внешнего хранилища Вашего приложения, которые система удалит, когда пользователь деинсталлирует Ваше приложение. Например, вот метод, которым Вы можете создать директорию индивидуального фотоальбома:
Если ни одно из предварительно определенных имен поддиректорий не подходит для Ваших файлов, то Вы можете вместо этого вызвать getExternalFilesDir() и передать null. Это возвратит корневую частную директорию для Вашего приложения на external storage.
Помните, что getExternalFilesDir() создает директорию внутри директории, которая будет удалена при деинсталляции Вашего приложения. Если файлы, которые Вы сохраняете, должны оставаться доступными после того, как пользователь деинсталлирует Ваше приложение - как например если Ваше приложение работает с фотокамерой, и пользователь хотел бы сохранить сделанные фотографии — Вы должны вместо этого использовать getExternalStoragePublicDirectory() .
Независимо от того, используете ли Вы для публичных файлов getExternalStoragePublicDirectory() или getExternalFilesDir() для частных файлов приложения, важно иметь в виду, что Вы используете имена директорий, предоставленные константами API наподобие DIRECTORY_PICTURES . Эти имена директорий гарантируют, что система будет правильно рассматривать эти файлы. Например файлы, сохраненные в DIRECTORY_RINGTONES , будут рассортированы медиасканером системы как рингтоны вместо музыки.
[Опрос количества свободного места]
Если Вы знаете заранее, сколько файлов сохраняете, то можете без получения ошибок IOException узнать, сколько места осталось путем вызова getFreeSpace() или getTotalSpace() . Эти методы предоставляют соответственно текущее доступное пространство и общее пространство на томе хранения. Эта информация также полезна, чтобы избежать переполнения тома хранения свыше определенного порога.
Однако система не гарантирует, что Вы можете записать столько байт, сколько показывает вызов getFreeSpace(). Если возвращенное количество всего на несколько мегабайт больше, чем Вам нужно сохранить, или если файловая система уже заполнена меньше, чем на 90%, то вероятно сохранение будет безопасным. Иначе возможно, что записать данные в хранилище не получится.
Внимание: Вам не обязательно проверять количество свободного места перед сохранения файла. Вместо этого Вы можете попробовать записать файл сразу же, и затем перехватить исключение IOException, если оно произойдет. Вы возможно, должны так поступить, когда не знаете, сколько места Вам нужно. Например, если Вы меняете способ кодирования файла перед его сохранением, преобразовывая картинку PNG в JPEG, то Вы не будете знать размер файла заранее.
[Удаление файла]
Вы всегда должны удалять файлы, которые Вам больше не нужны. Самый прямой способ удаления файла состоит в том, чтобы иметь этот файл открытым и вызвать delete() для самого себя.
Если файл сохранен на internal storage, Вы можете также запросить Context, чтобы найти и удалить файл вызовом deleteFile():
Внимание: когда пользователь деинсталлирует Ваше приложение, система Android удалит следующее:
• Все файлы, сохраненные Вашим приложением на internal storage.
• Все файлы, сохраненные Вашим приложением с использованием getExternalFilesDir().
Однако Вы должны регулярно удалять все кэшируемые файлы, создаваемые с getCacheDir(), и также регулярно удалять файлы, которые Вам больше не нужны.
[Пример записи файла на sdcard0]
Предположим, что необходимо записать какой-нибудь тестовый файл (с именем myFile.txt) в папку myFolder на внешний носитель, который виден в системе Android как sdcard0. Т. е. полный путь должен выглядеть примерно так:
Базовый путь до External Storage
Проблема тут состоит в том, чтобы узнать часть пути basePath, поскольку на разных системах Android этот путь будет разным, в зависимости от версии и внутреннего аппаратного устройства. В моем телефоне Samsung Galaxy Note этот basePath = /storage/sdcard0 , но это еще не значит, что на Вашем телефона этот путь будет именно таким. Чтобы получить basePath, используйте вызов функции getExternalStorageDirectory :
Проверка доступности носителя данных в External Storage
Вторая проблема состоит в доступности на запись носителя данных. Дело в том, что записать на носитель можно не всегда, например если он смонтирован как флешка USB (когда Ваш телефон подключен к компьютеру в режиме Mass Storage Device, USB MSD). Проверить доступность носителя можно следующей функцией:
Разрешение доступа к носителю данных в файле манифеста
Как уже упоминалось, необходимо в файле манифеста запросить разрешение WRITE_EXTERNAL_STORAGE . Вот пример такого файла манифеста:
Функция, которая сохраняет файл, принимая полный путь до файла filePath и сохраняемый текст FileContent:
Вызов функции SaveFile, который выполняет задачу сохранения файла в External-носителе:
[Пример записи файла на extSdCard]
Получение полного корневого пути до извлекаемой карты SD не так прост, как до External Storage, поскольку в API Android для этого почему-то не предусмотрены специальные простые функции. Приходится получать путь окольными путями, через имена системных папок. Вот код функции, которая получает путь до извлекаемой карты SD:
Вызов функции SaveFile, который выполняет задачу сохранения файла на извлекаемой карте SD:
[Сохранение бинарного файла (массива byte[])]
В предыдущих примерах мы рассматривали класс OutputStreamWriter , который позволяет записать строку String или массив символов char[]. Но как быть, если нужно записать массив байт byte[]? Для этого подойдет класс DataOutputStream . Пример:
Примеры вызовов getAbsolutePath:
[Ссылки]
Комментарии
В новых Android доступ на запись надо оформлять не в Манифесте. Вот что пишут: "Android added new permission model for Android 6.0 (Marshmallow). What Are Runtime Permissions? With Android 6.0 Marshmallow, Google introduced a new permission model that allows users to better understand why an application may be requesting specific permissions. Rather than the user blindly accepting all permissions at install time, the user is now prompted to accept permissions as they become necessary during application use.
microsin: ИМХО, это предупреждение чисто информационное, ничего не поменялось, разве что название. Раньше было все то же самое - перед установкой приложения Android показывает пользователю, какие действия будут разрешены приложению. Если пользователь согласен, то он подтверждает действие и установка продолжится, если нет - приложение не установится.
Читайте также: