Android
Хранение файлов во внутреннем и внешнем хранилищах
Поиск…
Синтаксис
- FileOutputStream openFileInput (имя строки)
- FileOutputStream openFileOutput (имя строки, режим int)
- Файл (File dir, String name)
- Файл (строка)
- Файл getExternalStoragePublicDirectory (тип строки)
- Файл getExternalFilesDir (тип строки)
параметры
параметр | подробности |
---|---|
название | Имя файла для открытия. ПРИМЕЧАНИЕ. Нельзя содержать разделители путей |
Режим | Рабочий режим. Используйте MODE_PRIVATE для работы по умолчанию и MODE_APPEND чтобы добавить существующий файл. Другие режимы включают MODE_WORLD_READABLE и MODE_WORLD_WRITEABLE , которые оба устарели в API 17. |
реж | Каталог файла для создания нового файла в |
дорожка | Путь для указания местоположения нового файла |
тип | Тип каталога файлов для извлечения. Может быть null или любым из следующих: DIRECTORY_MUSIC , DIRECTORY_PODCASTS , DIRECTORY_RINGTONES , DIRECTORY_ALARMS , DIRECTORY_NOTIFICATIONS , DIRECTORY_PICTURES или DIRECTORY_MOVIES |
Использование внутреннего хранилища
По умолчанию любые файлы, которые вы сохраняете во внутреннем хранилище, являются приватными для вашего приложения. К другим приложениям и пользователям при обычных условиях они не могут быть доступны. Эти файлы удаляются, когда пользователь удаляет приложение .
Запись текста в файл
String fileName= "helloworld";
String textToWrite = "Hello, World!";
FileOutputStream fileOutputStream;
try {
fileOutputStream = openFileOutput(fileName, Context.MODE_PRIVATE);
fileOutputStream.write(textToWrite.getBytes());
fileOutputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
Добавление текста в существующий файл
Используйте Context.MODE_APPEND
для параметра режима openFileOutput
fileOutputStream = openFileOutput(fileName, Context.MODE_APPEND);
Использование внешнего хранилища
«Внешнее» хранилище - это еще один тип хранилища, который мы можем использовать для сохранения файлов на устройстве пользователя. Он имеет некоторые ключевые отличия от «внутреннего» хранилища, а именно:
- Это не всегда доступно. В случае съемного носителя (SD-карта) пользователь может просто удалить хранилище.
- Это не личное. У пользователя (и других приложений) есть доступ к этим файлам.
- Если пользователь удаляет приложение, файлы, которые вы сохраняете в каталоге, полученном с помощью
getExternalFilesDir()
будут удалены.
Чтобы использовать Внешнее хранилище, мы должны сначала получить соответствующие разрешения. Вам нужно будет использовать:
-
android.permission.WRITE_EXTERNAL_STORAGE
для чтения и записи -
android.permission.READ_EXTERNAL_STORAGE
только для чтения
Чтобы предоставить эти разрешения, вам необходимо будет идентифицировать их в вашем AndroidManifest.xml
как таковые
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
ПРИМЕЧАНИЕ. Поскольку они являются опасными разрешениями, если вы используете API-уровень 23 или выше, вам нужно будет запросить разрешения во время выполнения .
Перед попыткой записи или чтения из внешнего хранилища вы всегда должны проверить, доступен ли носитель данных.
String state = Environment.getExternalStorageState();
if (state.equals(Environment.MEDIA_MOUNTED)) {
// Available to read and write
}
if (state.equals(Environment.MEDIA_MOUNTED) ||
state.equals(Environment.MEDIA_MOUNTED_READ_ONLY)) {
// Available to at least read
}
При записи файлов во внешнее хранилище вы должны решить, должен ли файл быть общедоступным или приватным. Хотя оба этих типа файлов по-прежнему доступны для пользователя и других приложений на устройстве, существует различие между ними.
Публичные файлы должны оставаться на устройстве, когда пользователь удаляет приложение. Примером файла, который должен быть сохранен как «Публичный», являются фотографии, которые были сделаны через ваше приложение.
Частные файлы должны быть удалены, когда пользователь удалит приложение. Эти типы файлов будут специфичными для приложения и не будут использоваться для пользователей или других приложений. Ex. временные файлы, загруженные / используемые вашим приложением.
Вот как получить доступ к папке « Documents
как для общедоступных, так и для частных файлов.
общественного
// Access your app's directory in the device's Public documents directory
File docs = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DOCUMENTS), "YourAppDirectory");
// Make the directory if it does not yet exist
myDocs.mkdirs();
Частный
// Access your app's Private documents directory
File file = new File(context.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS),
"YourAppDirectory");
// Make the directory if it does not yet exist
myDocs.mkdirs();
Android: внутреннее и внешнее хранилище - уточнение терминологии
Разработчики Android (в основном новички) путались относительно терминологии внутреннего и внешнего хранилищ. Есть много вопросов по Stackoverflow относительно того же. Это в основном из-за того, что терминология в соответствии с официальной документацией Google / официального Android совсем отличается от терминологии обычного пользователя ОС Android. Поэтому я думал, что документальное подтверждение поможет.
Что мы думаем - терминология пользователя (UT)
Внутреннее хранилище (UT) | Внешнее хранилище (UT) |
---|---|
встроенная внутренняя память телефона | съемная карта Secure Digital (SD) или micro SD |
Пример: 32 ГБ внутренней памяти Nexus 6P. | Пример: место для хранения на съемных SD-картах, поставляемых такими поставщиками, как samsung, sandisk, strontium, transcend и другие |
Но, согласно Android Documentation / Guide - терминология Google (GT)
Внутреннее хранилище (GT):
По умолчанию файлы, сохраненные во внутреннем хранилище, являются приватными для вашего приложения, а другие приложения не могут получить к ним доступ (а также не могут).
Внешнее хранилище (GT):
Это может быть съемный носитель (например, SD-карта) или внутреннее (несъемное) хранилище.
Внешнее хранилище (GT) можно разделить на два типа:
Первичное внешнее хранилище | Вторичное внешнее хранилище или съемное хранилище (GT) |
---|---|
Это то же самое, что встроенная внутренняя память телефона (или) Внутреннее хранилище (UT) | Это то же самое, что и съемное хранилище micro SD-карт (или) Внешнее хранилище (UT) |
Пример: 32 ГБ внутренней памяти Nexus 6P. | Пример: место для хранения на съемных SD-картах, поставляемых такими поставщиками, как samsung, sandisk, strontium, transcend и другие |
Этот тип хранилища можно получить на ПК с Windows, подключив телефон к ПК через USB-кабель и выбрав « Камера» (PTP) в уведомлении о настройках USB. | Этот тип хранилища можно получить на ПК с Windows, подключив телефон к ПК через USB-кабель и выбрав « Передача файлов» в уведомлении о параметрах USB. |
В двух словах,
Внешнее хранилище (GT) = Внутреннее хранилище (UT) и внешнее хранилище (UT)
Съемное хранилище (GT) = Внешнее хранилище (UT)
Внутреннее хранилище (GT) не имеет термина в UT.
Позвольте мне объяснить,
Внутреннее хранилище (GT): по умолчанию файлы, сохраненные во внутреннем хранилище, являются приватными для вашего приложения, а другие приложения не могут получить к ним доступ. Пользователь вашего приложения также не может получить к ним доступ с помощью диспетчера файлов; даже после включения опции «показать скрытые файлы» в диспетчере файлов. Чтобы получить доступ к файлам во внутреннем хранилище (GT), вам необходимо укрепить свой телефон Android. Более того, когда пользователь удаляет ваше приложение, эти файлы удаляются / удаляются.
Так Internal Storage (GT) является не то , что мы думаем , как внутренняя память 32/64 Гб Nexus 6P в
Как правило, местоположение внутреннего хранилища (GT) будет: /data/data/your.application.package.appname/someDirectory/
Внешнее хранилище (GT):
Каждое Android-совместимое устройство поддерживает общую «внешнюю память», которую вы можете использовать для сохранения файлов. Файлы, сохраненные во внешнем хранилище, читаются в мире и могут быть изменены пользователем при включении массовой памяти USB для передачи файлов на компьютер.
Расположение внешнего хранилища (GT): оно может быть в любом месте вашего внутреннего хранилища (UT) или на съемном носителе (GT), то есть на карте micro SD. Это зависит от OEM вашего телефона, а также от версии ОС Android.
Чтобы читать или записывать файлы на внешнем хранилище (GT), ваше приложение должно получить системные разрешения READ_EXTERNAL_STORAGE
или WRITE_EXTERNAL_STORAGE
.
Например:
<manifest ...>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
...
</manifest>
Если вам нужно как читать, так и записывать файлы, вам необходимо запросить только разрешение
WRITE_EXTERNAL_STORAGE
, так как оно также требует доступа к чтению.
В External Storage (GT) вы также можете сохранять файлы, закрытые для приложения
Но,
Когда пользователь удаляет ваше приложение, этот каталог и все его содержимое удаляются.
Когда вам нужно сохранять файлы, закрытые для приложения, в External Storage (GT) ?
Если вы обрабатываете файлы, которые не предназначены для использования другими приложениями (например, графические текстуры или звуковые эффекты, используемые только вашим приложением), вы должны использовать личный каталог хранилища на внешнем хранилище
Начиная с Android 4.4, чтение или запись файлов в личных каталогах вашего приложения не требует
READ_EXTERNAL_STORAGE
илиWRITE_EXTERNAL_STORAGE
. Таким образом, вы можете заявить, что разрешение должно запрашиваться только в более низких версиях Android, добавив атрибутmaxSdkVersion
:
<manifest ...>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="18" />
...
</manifest
Способы хранения во внутреннем хранилище (GT):
Оба эти метода присутствуют в классе Context
File getDir (String name, int mode)
File getFilesDir ()
Способы хранения в основном внешнем хранилище, т.е. внутреннем хранилище (UT):
File getExternalStorageDirectory ()
File getExternalFilesDir (String type)
File getExternalStoragePublicDirectory (String type)
В начале все использовали Environment.getExternalStorageDirectory () , который указывал на корень Первичного внешнего хранилища . В результате первичное внешнее хранилище было заполнено случайным контентом.
Позже эти два метода были добавлены:
В классе
Context
они добавили getExternalFilesDir () , указав на каталог приложения для первичного внешнего хранилища. Этот каталог и его содержимое будут удалены, когда приложение будет удалено .Environment.getExternalStoragePublicDirectory () для централизованных мест для хранения известных типов файлов, таких как фотографии и фильмы. Этот каталог и его содержимое НЕ удаляются при удалении приложения.
Способы хранения в съемном хранилище (GT), то есть карта micro SD
До уровня API 19 не было официального способа хранения на SD-карте. Но многие могли сделать это с помощью неофициальных библиотек или API.
Официально один метод был введен в классе Context
в API 19 (Android версии 4.4 - Kitkat).
File[] getExternalFilesDirs (String type)
Он возвращает абсолютные пути к каталогам конкретных приложений на всех устройствах общего доступа / внешних устройств хранения, где приложение может размещать постоянные файлы, которыми он владеет. Эти файлы являются внутренними для приложения и обычно не видны пользователю как носители.
Это означает, что он вернет пути к обоим типам внешнего хранилища (GT) - Внутренняя память и карта Micro SD. Обычно второй путь - это путь хранения микро SD-карты (но не всегда). Поэтому вам нужно проверить это, выполнив код с помощью этого метода.
Пример с фрагментом кода:
Я создал новый проект андроида с пустой активностью, написал следующий код внутри
protected void onCreate(Bundle savedInstanceState)
метод MainActivity.java
File internal_m1 = getDir("custom", 0);
File internal_m2 = getFilesDir();
File external_m1 = Environment.getExternalStorageDirectory();
File external_m2 = getExternalFilesDir(null);
File external_m2_Args = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File external_m3 = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
File[] external_AND_removable_storage_m1 = getExternalFilesDirs(null);
File[] external_AND_removable_storage_m1_Args = getExternalFilesDirs(Environment.DIRECTORY_PICTURES);
После выполнения выше кода,
Выход:
internal_m1: /data/data/your.application.package.appname/app_custom
internal_m2: /data/data/your.application.package.appname/files
external_m1: /storage/emulated/0
external_m2: /storage/emulated/0/Android/data/your.application.package.appname/files
external_m2_Args: /storage/emulated/0/Android/data/your.application.package.appname/files/Pictures
external_m3: /storage/emulated/0/Pictures
external_AND_removable_storage_m1 (first path):
/storage/emulated/0/Android/data/your.application.package.appname/files
external_AND_removable_storage_m1 (second path):
/storage/sdcard1/Android/data/your.application.package.appname/files
external_AND_removable_storage_m1_Args (first path):
/storage/emulated/0/Android/data/your.application.package.appname/files/Pictures
external_AND_removable_storage_m1_Args (second path): /storage/sdcard1/Android/data/your.application.package.appname/files/Pictures
Примечание. Я подключил свой телефон к ПК с ОС Windows; включил обе опции разработчика, отладку USB и затем запустил этот код. Если вы не подключите свой телефон ; но вместо этого запускайте это на эмуляторе Android , ваш выход может отличаться. Моя модель телефона - Coolpad Note 3 - работает на Android 5.1
Место хранения на моем телефоне:
Место хранения микро SD : /storage/sdcard1
Внутреннее хранилище (UT) : /storage/sdcard0
.
Обратите внимание, что /sdcard
& /storage/emulated/0
/sdcard
/storage/emulated/0
также указывают на внутреннее хранилище (UT). Но это символические /storage/sdcard0
на /storage/sdcard0
.
Чтобы четко понимать разные пути хранения в Android, пройдите этот ответ
Отказ от ответственности: все упомянутые выше пути хранения - это пути на моем телефоне. Ваши файлы могут не храниться на одинаковых путях хранения. Поскольку места хранения / пути хранения могут отличаться на других мобильных телефонах в зависимости от вашего поставщика, производителя и различных версий ОС Android.
Сохранить базу данных на SD-карте (резервная БД на SD)
public static Boolean ExportDB(String DATABASE_NAME , String packageName , String folderName){
//DATABASE_NAME including ".db" at the end like "mayApp.db"
String DBName = DATABASE_NAME.substring(0, DATABASE_NAME.length() - 3);
File data = Environment.getDataDirectory();
FileChannel source=null;
FileChannel destination=null;
String currentDBPath = "/data/"+ packageName +"/databases/"+DATABASE_NAME; // getting app db path
File sd = Environment.getExternalStorageDirectory(); // getting phone SD card path
String backupPath = sd.getAbsolutePath() + folderName; // if you want to set backup in specific folder name
/* be careful , foldername must initial like this : "/myFolder" . dont forget "/" at begin of folder name
you could define foldername like this : "/myOutterFolder/MyInnerFolder" and so on ...
*/
File dir = new File(backupPath);
if(!dir.exists()) // if there was no folder at this path , it create it .
{
dir.mkdirs();
}
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss");
Date date = new Date();
/* use date including file name for arrange them and preventing to make file with the same*/
File currentDB = new File(data, currentDBPath);
File backupDB = new File(backupPath, DBName +"("+ dateFormat.format(date)+").db");
try {
if (currentDB.exists() && !backupDB.exists()) {
source = new FileInputStream(currentDB).getChannel();
destination = new FileOutputStream(backupDB).getChannel();
destination.transferFrom(source, 0, source.size());
source.close();
destination.close();
return true;
}
return false;
} catch(IOException e) {
e.printStackTrace();
return false;
}
}
вызовите этот метод следующим образом:
ExportDB ( "myDB.db", "com.example.exam", "/ MyFolder");
Выбор каталога устройств:
Сначала добавьте разрешение на хранение для чтения / извлечения каталога устройства.
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
Создать класс модели
//create one directory model class
//to store directory title and type in list
public class DirectoryModel {
String dirName;
int dirType; // set 1 or 0, where 0 for directory and 1 for file.
public int getDirType() {
return dirType;
}
public void setDirType(int dirType) {
this.dirType = dirType;
}
public String getDirName() {
return dirName;
}
public void setDirName(String dirName) {
this.dirName = dirName;
}
}
Создайте список, используя модель каталога, чтобы добавить данные каталога.
//define list to show directory
List<DirectoryModel> rootDir = new ArrayList<>();
Fetch, используя следующий метод.
//to fetch device directory
private void getDirectory(String currDir) { // pass device root directory
File f = new File(currDir);
File[] files = f.listFiles();
if (files != null) {
if (files.length > 0) {
rootDir.clear();
for (File inFile : files) {
if (inFile.isDirectory()) { //return true if it's directory
// is directory
DirectoryModel dir = new DirectoryModel();
dir.setDirName(inFile.toString().replace("/storage/emulated/0", ""));
dir.setDirType(0); // set 0 for directory
rootDir.add(dir);
} else if (inFile.isFile()) { // return true if it's file
//is file
DirectoryModel dir = new DirectoryModel();
dir.setDirName(inFile.toString().replace("/storage/emulated/0", ""));
dir.setDirType(1); // set 1 for file
rootDir.add(dir);
}
}
}
printDirectoryList();
}
}
Печатать список каталогов в журнале.
//print directory list in logs
private void printDirectoryList() {
for (int i = 0; i < rootDir.size(); i++) {
Log.e(TAG, "printDirectoryLogs: " + rootDir.get(i).toString());
}
}
использование
//to Fetch Directory Call function with root directory.
String rootPath = Environment.getExternalStorageDirectory().toString(); // return ==> /storage/emulated/0/
getDirectory(rootPath );
Для извлечения внутренних файлов / папки определенного каталога используйте тот же самый метод, просто измените аргумент, передайте текущий выбранный путь в аргументе и ответьте дескриптор для этого.
Чтобы получить расширение файла:
private String getExtension(String filename) {
String filenameArray[] = filename.split("\\.");
String extension = filenameArray[filenameArray.length - 1];
Log.d(TAG, "getExtension: " + extension);
return extension;
}