Сохранение файлов в Android - для начинающих (внутреннее / внешнее хранилище)

Я новичок в разработке Android, и мне нужна помощь новичков, пожалуйста ...

Я создаю приложение, которое должно иметь 2 каталога, каталог баз данных и каталог изображений, как и в Whatsapp.

Я хочу видеть эти каталоги в диспетчере файлов, когда просматриваю свой телефон, так же, как вы видите папки других приложений. Я попробовал все, что нашел здесь, чтобы создать это во внутреннем хранилище и во внешнем хранилище из кода. Кажется, что папки созданы, но когда я просмотрел диспетчер файлов своего телефона, я не смог найти папку с именем моего приложения и внутри нее мои папки с базами данных и изображениями ... Что я делаю неправильно? мне нужно создать эти папки в студии Android как добавляющие папки? или мне нужно создать его из кода?

Не могли бы вы рассказать мне о действиях, которые мне нужно сделать для выполнения этой задачи? Я использую android studio 3.1.3. Спасибо за помощников! :)

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
12
0
21 049
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

Термины «Внутреннее хранилище» и «Внешнее хранилище» могут сначала сбивать с толку, потому что намерения Google отличаются от того, что мы ожидаем и знаем из повседневного использования языка: «Внешний» не обязательно означает «SD-карта. ". Этот парень написал отличную статью о путанице в терминологии

Согласно вашим намерениям, вы хотите работать с концепцией Внешнее хранилище. Различия хорошо объяснены в Документация, но я кратко расскажу о них здесь.

В конце я приведу вам пример, но сначала расскажу об основах:

Внутреннее хранилище

  • Файлы доступны по только ваше приложение
  • Файлы удаляются при удалении вашего приложения
  • Файлы всегда доступны (это означает, что они никогда не будут сохранены на съемной памяти)

Внешнее хранилище

  • Файлы полностью читаются Другие приложения (включая любой вариант приложения File Manager, в вашем случае)
  • Файлы не обязательно удаляются при удалении вашего приложения - объяснено позже.
  • Доступность файлов не гарантируется (могут быть удалены другими приложениями / съемной памятью)

Итак, теперь, когда мы знаем, что вам нужно внешнее хранилище, перед запуском необходимо сделать несколько вещей:

  • Требовать разрешения (чтение / запись) внутри вашего файла Manifest.xml, в зависимости от ваших потребностей:
    <manifest ...>
    <uses-permission android:name = "android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name = "android.permission.WRITE_EXTERNAL_STORAGE" />
    ...
    </manifest>

Каждое разрешение стоит отдельно, а это означает, что вам не нужно иметь оба, если, например, вы хотите только читать файлы, а не записывать их.

  • Убедитесь, что доступно хранилище - это делается во время выполнения и хорошо объяснено в документации. Нам нужно убедиться, что хранилище подключено к устройству / его состояние не вызывает проблем, что может вызвать сбой запросов на чтение / запись.

Время для примера!

В данном методе мы сохраним текстовый файл внутри корневого каталога.

Кредиты для эта статья

public void writeFileExternalStorage() {

    //Text of the Document
    String textToWrite = "bla bla bla";

    //Checking the availability state of the External Storage.
    String state = Environment.getExternalStorageState();
    if (!Environment.MEDIA_MOUNTED.equals(state)) {

        //If it isn't mounted - we can't write into it.
        return;
    }

    //Create a new file that points to the root directory, with the given name:
    File file = new File(getExternalFilesDir(null), filenameExternal);

    //This point and below is responsible for the write operation
    FileOutputStream outputStream = null;
    try {
        file.createNewFile();
        //second argument of FileOutputStream constructor indicates whether
        //to append or create new file if one exists
        outputStream = new FileOutputStream(file, true);

        outputStream.write(textToWrite.getBytes());
        outputStream.flush();
        outputStream.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

Хочу конкретно ответить на некоторые из ваших вопросов:

do I need to create those folders in the android studio as adding folders? or do I need to create it from code?

Определенно не через Android Studio. Это папка ваших проектов, содержащая ваш код. Как это сделать, указано выше.

I couldn't find the folder with my app name and inside it my Databases and Images folders... What am I doing wrong?

Вероятно, вы сохранили ваши файлы как файлы внутреннего хранилища / сохранили их как папки проекта, как вы упомянули ранее - и они не будут (и не должны) отображаться.


Полезные вещи знать

Есть 2 типа каталогов: публичные и частные.

Частный

  • Недоступно в магазине мультимедиа
  • Файлы удаляются при удалении приложения
  • Получено методом getExternalFilesDir(...)

Пример: каталог WhatsApp (в моем телефоне) находится прямо на корневом уровне. Назвать это будет: getExternalFilesDir("WhatsApp/...")

Общественные (Загрузки / Фильмы / Библиотеки изображений)

  • Файлы сканируются MediaStore
  • Получено методом Environment.getExternalStoragePublicDirectory(...)

Пример: получение папки Documents будет выглядеть так: Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS)

Большое спасибо за подробный и быстрый ответ! еще один вопрос по этому поводу. путь к файлу, который я создал, на моем телефоне: /storage/emulated/0/Android/data/com.example.../files/FileNa‌ меня, когда я использовал getExternalFilesDir. Я хотел создать каталоги в: / storage / emulated / 0 / AppName, поэтому я использовал Environment.getExternalStorageDirectory (). При отладке путь был правильным, и казалось, что папка создана, но я не могу найти ее на телефоне и на компьютере. где я ошибся здесь? для WhatsApp, например, путь / storage / emulated / 0 / WhatsApp /

Shlomi 28.07.2018 23:23

Код, который я использовал для создания папки: String DirName = "MyAppName"; Файл dir = новый файл (Environment.getExternalStorageDirectory (), DirName); если (! dir.exists ()) {dir.mkdirs (); }

Shlomi 28.07.2018 23:24

Я думаю, вы хотите использовать new File(getExternalFilesDir(), DirName) вместо getExternalStoragePublicDirectory(). Другое дело: файл должен указывать на файл, а не на каталог. попробуйте изменить DirName на "MyAppName / TestFile.txt" и посмотрите, работает ли это для вас

Barak 28.07.2018 23:33

С getExternalFilesDir () путь будет /storage/emulated/0/Android/data/com.example.../DirName/file‌ s /, и я хочу, чтобы путь был / storage / emulated / 0 / DirName /. использует новый файл (Environment.getExternalStorageDirectory (), DirName), если это неверно? а для изменения DirName на «MyAppName / TestFile.txt» я хочу создать пустой каталог и заполнить его командами приложения в коде. Есть ли другой способ сделать это? а почему я не вижу созданный каталог? Еще раз спасибо всем за помощь! :) (תודה רבה!)

Shlomi 28.07.2018 23:48

И как правильно создать пустой каталог, не используя File?

Shlomi 28.07.2018 23:54

Прошу прощения - запуталась насчет getExternalFilesDir. Я выяснил, в чем может быть ваша проблема (я сам пробовал сейчас, она работает) - проблема с разрешением: перейдите в настройки телефона -> приложения -> найдите свое приложение и установите для разрешения хранилища значение true. Кроме того, перед публикацией приложения вам нужно создать всплывающее диалоговое окно с запросом разрешения для пользователей с версией Android> 6 (Marshmallow). настройки разрешения в Manifest.xml недостаточно для Marshmallow и выше. Попробуйте и дайте мне знать, сработало ли это. יף :)

Barak 29.07.2018 00:30

Да, сработало! вот в чем проблема! Спасибо, вы мне очень помогли! :) מעריכה, תודה רבה! :)

Shlomi 29.07.2018 01:07
outputStream.write(cashback.getBytes()) - я думаю, вы имели в виду textToWrite, а не cashback. ;)
Neph 18.03.2020 13:41

Главный ответ действительно помог мне, и я не смог бы до него добраться без этого отличного ответа.

Но у меня возникли некоторые трудности с получением каталога хранилища (из-за изменений в API с течением времени), и я использую Kotlin, поэтому я подумал, что просто поделюсь своим последним кодом, который я использовал.

Mine также возвращает сообщение String (абсолютный путь к файлу - успех, в противном случае - сообщение об ошибке).

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

fun writeFileExternalStorage() :String {

        var fileData : String = "test this"
        
        Log.i("FirstFrag", "in writeFileExternalStorage")
        //Checking the availability state of the External Storage.
        val state = Environment.getExternalStorageState()
        if (Environment.MEDIA_MOUNTED != state) {

            Log.i("FirstFrag", "Couldn't get file system.")
            return "Couldn't write file."
        }

        var file =File(requireContext().getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), "test.txt")

        Log.i("FirstFrag", file.absolutePath)
        //This point and below is responsible for the write operation
        var outputStream: FileOutputStream? = null
        try {
            Log.i("FirstFrag", "creating new file")
            file.createNewFile()
            Log.i("FirstFrag", "file created")
            //second argument of FileOutputStream constructor indicates whether
            //to append or create new file if one exists
            outputStream = FileOutputStream(file, true)
            outputStream?.write(fileData.toByteArray())
            outputStream?.flush()
            outputStream?.close()
            Log.i("FirstFrag", "wrote file!")
            return file.absolutePath
        } catch (e: Exception) {
            Log.i("FirstFrag",e.message.toString())
            return e.message.toString() + "\nPlease check that you have a valid filename."
        }
        finally {
            isRetrievingFile = false;
        }
    }

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