Ваш IP: 18.97.14.87






    Демистификация внутренней и внешней памяти в современном Android

    Демистификация внутренней и внешней памяти в современном Android

    Том Колвин

    7 минут чтения

    16 января

    Обновлено 6 февраля 2023 г.

    Изображение SD-карты на цветном фоне
    Изображение Рави Шармы

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

    Давайте отправимся в путешествие, чтобы понять, почему существуют эти варианты, какой вариант вам следует выбрать и какие есть лучшие альтернативы.

    Раньше Android был простым, но безумно небезопасным

    В старые времена у внутреннего и внешнего выбора были разные цели:

    • Внутреннее хранилище означало внутреннюю память устройства. Файлы, хранящиеся здесь, были заблокированы для вашего приложения, а это означает, что другие приложения не могли получить к ним доступ независимо от их разрешений.
    • Внешнее хранилище означало все, что не было внутренней памятью устройства, например вставленную SD-карту. Это использовалось как общедоступное место, к которому могло получить доступ любое приложение, если у этого приложения были правильные разрешения.

    Хотя это было ясно, у него была особая проблема: устройства того времени имели очень мало внутренней памяти и полагались на то, что пользователи подключали SD-карты. SD-карты по определению были внешним хранилищем.

    Поэтому, если вы хотели хранить большой объем данных — скажем, вы писали приложение для фотографий — у вас действительно был выбор только во внешнем хранилище. Поэтому приложения часто запрашивали разрешение на доступ к внешнему хранилищу (через разрешения READ_EXTERNAL_STORAGE и WRITE_EXTERNAL_STORAGE).

    Но это было крайне небезопасно. Эти разрешения на внешнее хранилище позволят приложению читать/записывать файлы в любом месте на SD-карте. Таким образом, все ваши фотографии стали доступны любому приложению, желающему записать свои данные во внешнее хранилище. А поскольку разрешения на внешнее хранилище так часто запрашивались приложениями, пользователи предоставляли их без какого-либо реального рассмотрения. Отслеживайте вредоносные приложения, которые крадут ваши данные без вашего ведома.

    Android KitKat: упрощенные разрешения повысили безопасность (!!)

    Вопрос : Как можно решить проблему безопасности, ослабив разрешения, необходимые для каких-либо действий?

    Ответ : Психология человека. Ослабляя разрешения, необходимые для выполнения неопасных вещей, вы заставляете людей сидеть и обращать внимание, когда запрашивается разрешение .

    Android KitKat улучшил безопасность хранилища, ослабив разрешения (фото: Google)

    Это то, что сделал Android 4.4 (KitKat). Впервые он позволил приложениям получать доступ к своим собственным уникальным местам во внешнем хранилище без разрешения. Теперь, когда приложение вызывает getExternalFilesDir(), оно создает свой собственный каталог, из которого оно может свободно читать и писать.

    Разрешения READ_EXTERNAL_STORAGE и WRITE_EXTERNAL_STORAGE по-прежнему необходимы для чтения/записи где-либо еще во внешнем хранилище, но дело в том, что большинству приложений это никогда не понадобится.

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

    Эмулированное внешнее хранилище: когда внутреннее хранилище становится внешним

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

    И телефоны постепенно перестали предлагать внешнее хранилище. Это вызвало проблему со старыми приложениями, которые ожидали, что только внешнее хранилище будет достаточно большим для их нужд, и слепо использовали getExternalFilesDir() .

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

    Начиная с API 21, приложения могут использовать Environment.isExternalStorageEmulated() , чтобы определить, имеет ли устройство физическое или эмулированное внешнее хранилище. Для подавляющего большинства современных Android-устройств он будет эмулироваться.

    Приемлемое внешнее хранилище: когда внешнее хранилище становится внутренним

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

    Положительные моменты : это позволяет устройствам с низкими характеристиками безопасно увеличивать внутреннюю память.

    Плохие моменты : принятая SD-карта, скажем, неразрывно связана с этим телефоном. Удалите его, и ваш телефон станет странным : вы, по сути, удалили случайный фрагмент его приложений и данных. (Случайно, потому что ОС, а не пользователь выбирает, будет ли что-то установлено или сохранено во внутренней или принятой памяти.) Я не могу представить, чтобы какая-либо ОС могла справиться с этим очень хорошо.

    Scoped Storage в Android 10 полностью изменил внешнее хранилище

    Логотип Android 10
    Android 10 полностью изменил принцип работы хранилища (изображение: Google)

    Android 10 представил Scoped Storage для внешнего хранилища. По сути, это сделало безопасность внешнего хранилища очень похожей на внутреннюю память. Приложения получат свой собственный каталог, к которому они смогут обращаться (чтение/запись) без разрешения, и ни одно другое приложение не сможет этого сделать (кроме см. ниже).

    Проблема с Scoped Storage заключалась в том, что в нем не учитывались некоторые важные варианты использования, которые ранее требовали бесплатного доступа к общему хранилищу. Например, как насчет доступа к фотогалерее пользователя? Эти варианты использования рассматривались в индивидуальном порядке. Они следующие:

    Разрешение пользователю выбирать из галереи фотографий

    Используйте средство выбора фотографий , никаких разрешений не требуется. (См. мою статью об использовании Photo Picker с Kotlin + Compose ).

    Анимация, показывающая, как работает средство выбора фотографий в Android 11+.
    Android Photo Picker, изображение предоставлено Google

    Обратите внимание, что это доступно только на Android 11+.

    Запись фотографий в библиотеку пользователя

    Используйте API-интерфейсы MediaStore . Для записи новых фотографий не требуется никаких разрешений.

    Чтение фотографий из библиотеки пользователя

    Также API MediaStore. Никаких разрешений не требуется, если вы получаете доступ только к файлам, созданным вашим собственным приложением. Если вы хотите получить доступ ко всей библиотеке, вам потребуются следующие разрешения:

    <!-- Требуется, только если вашему приложению требуется доступ к изображениям или фотографиям 
         , созданным другими приложениями. --> 
    < uses-permission  android:name = "android.permission.READ_MEDIA_IMAGES" /> 
    
    <!-- Требуется, только если вашему приложению требуется доступ к видео 
         , созданным другими приложениями. --> 
    < uses-permission  android:name = "android.permission.READ_MEDIA_VIDEO" /> 
    
    <!-- Требуется, только если вашему приложению требуется доступ к аудиофайлам 
         , созданным другими приложениями. --> 
    < использует-разрешение  android:name = "android.permission.READ_MEDIA_AUDIO" />
    
    <!-- Если вашему приложению не требуется доступ к медиафайлам, созданным другими приложениями, 
         вместо этого установите для атрибута "maxSdkVersion" значение "28". --> 
    < использование-разрешение  android:name = "android.permission.READ_EXTERNAL_STORAGE" 
                     android:maxSdkVersion = "32" /> 
    
    < использование-разрешение  android:name = "android.permission.WRITE_EXTERNAL_STORAGE" 
                     android:maxSdkVersion = "29" / >

    Создание, чтение и запись общих документов

    Например, если вы хотите сохранить файл PDF в месте, где другие файлы могут получить к нему доступ, или прочитать данные геотрекинга, которые были предоставлены другим приложением.

    Для этого вы можете использовать Documents Provider . Никаких разрешений не требуется, так как пользователь все равно вынужден участвовать в процессе выбора файла.

    Доступ к большим наборам данных, кэшированным другим приложением

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

    Этого можно добиться с помощью BlobStoreManager .

    Полный доступ ко всему во внешнем хранилище

    По-прежнему существует разрешение, которое позволяет пользователям получать доступ ко всему во внешнем хранилище, но сейчас его труднее получить. Это подходит только в очень ограниченных случаях, например, в приложениях для управления файлами, системах резервного копирования или антивирусных сканерах. Play Store не разрешает отправлять приложения с использованием этого разрешения без подходящего объяснения.

    Разрешение есть MANAGE_EXTERNAL_STORAGE. Приложения должны не только объявлять это разрешение, но и указывать пользователям включать его вручную. Активируйте ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSIONнамерение сделать это, что приводит пользователя сюда:

    Изображение диалогового окна разрешения управления всеми файлами
    Разрешение на доступ ко всем файлам, которое пользователь должен предоставить вручную.

    Отказ от ограниченного хранилища

    Хотя Scoped Storage был представлен в Android 10, это было настолько значительное изменение, что оно не применялось до Android 11. Даже тогда приложения, ориентированные на API 29, могли отказаться от него, поместив его в файл манифеста <application android:requestLegacyExternalStorage="true" />. Обратите внимание, что приложения, ориентированные на API 29, не принимались в Play Store уже много лет, поэтому он, по сути, больше не поддерживается.

    Итак, это вводит нас в курс дела. Текущая версия Android не претерпела существенных изменений в правах доступа к хранилищу после этого масштабного изменения в Android 10.

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

    Том Колвин — технический директор Conseal Security , экспертов по тестированию безопасности мобильных приложений; и Apptaura , специалисты по разработке приложений. Свяжитесь с нами , если я могу помочь с любыми проектами по безопасности мобильных устройств или разработками!

    Андроид
    Разработка приложений для Android
    Безопасность Android
    Безопасность

    Том Колвин

    Автор Том Колвин

    Андроид и безопасность. Технический директор Apptaura, специалисты по разработке приложений, и Conseal, эксперты по безопасности. Доступен в качестве внештатного консультанта/разработчика. Южная Англия.