Външното хранилище на мобилни устройства е сменяем носител на данни, до който може да получи достъп всяко приложение със съответните разрешения. Според Android Open Source Project, 2026, от Android 10 насам Google въведе Scoped Storage — модел, който ограничава директния достъп до файловата система и изисква използване на MediaStore API за работа с общи мултимедийни файлове. Този подход повишава сигурността на потребителските данни и предотвратява изтичане на информация между приложенията.
Основни моменти
READ_EXTERNAL_STORAGE и WRITE_EXTERNAL_STORAGE са задължителни за Android 9 и по-ниски версииВъншно хранилище е област от паметта, която не е част от защитената пясъчна среда на приложението и е достъпна за други програми. На Android под този термин обикновено се разбира SD карта, но към външното хранилище спадат също USB устройства, свързани чрез OTG адаптер, и облачни дискове, интегрирани на ниво файлова система. Основната разлика от вътрешното хранилище е липсата на изолация: файловете във външното хранилище могат да се четат и променят от всяко приложение с подходящи разрешения.
На Android външното хранилище е представено в два основни режима: преносим (portable) и вътрешен (adoptable). При форматиране на SD карта като преносимо хранилище тя остава сменяема и се форматира на FAT32 или exFAT. В режим adoptable storage картата се форматира на ext4 и се криптира с AES-128, след което системата я възприема като разширение на вътрешната памет. Режимът adoptable е достъпен от Android 6.0 Marshmallow, но производителите на устройства често изключват тази възможност в своите фърмуери. Според статистиката на Google Play Console само около 12% от Android устройствата поддържат adoptable storage, поради което не се препоръчва да разчитате единствено на разширяване на вътрешната памет чрез SD карта.
На iOS няма традиционни SD карти. Apple използва затворена архитектура, където цялото съхранение се основава на вътрешна флаш памет и iCloud. Външни устройства се поддържат чрез Lightning или USB-C порт, но достъпът до тях е ограничен до системния файлов мениджър Files и приложения, които се интегрират с Document Picker. Потребителят сам решава кои файлове да отвори от външен източник — приложението не може да сканира свързаното устройство без изрично съгласие.
Изборът на външен носител зависи от изискванията за скорост, капацитет и преносимост. Различните типове носители имат различни скоростни характеристики, файлови системи и сценарии на използване в мобилни приложения.
| Тип носител | Макс. капацитет | Скорост на четене | Файлова система |
|---|---|---|---|
| SD UHS-I | 2 TB | до 104 MB/s | exFAT / FAT32 |
| SD UHS-II | 2 TB | до 312 MB/s | exFAT / FAT32 |
| USB 3.0 OTG | 2 TB | до 400 MB/s | exFAT / NTFS / FAT32 |
| USB-C SSD | 4 TB | до 1000 MB/s | exFAT / APFS / NTFS |
SD картите се класифицират по скорост на запис: Class 10 (10 MB/s), U1 (10 MB/s), U3 (30 MB/s), V30 (30 MB/s) и V90 (90 MB/s). За запис на 4K видео се изисква карта поне U3 или V30. За мобилни приложения, работещи с големи мултимедийни файлове (обработка на снимки, видеомонтаж), се препоръчва използването на карти от клас U3 и нагоре. Скоростта на картата пряко влияе върху производителността на приложението: записът на 4K видео на карта Class 10 може да причини пропускане на кадри поради недостатъчна честотна лента. При избор на SD карта за приложението обръщайте внимание не само на класа на скорост, но и на рейтинга Application Performance Class: A1 и A2 показват минимална производителност на произволно четене и запис, критична за работата на бази данни и кеш на приложения.
USB-OTG (On-The-Go) позволява свързване на външни USB устройства към мобилно устройство чрез адаптер. Android поддържа OTG от версия 3.1, но за монтиране на устройството се изисква ядро с поддръжка на файловата система. FAT32 и exFAT се поддържат директно, NTFS — само на устройства с персонализирано ядро или чрез библиотеката Paragon. На iOS поддръжката на USB устройства се появи в iOS 13 заедно с приложението Files. За работа с устройството приложението трябва да използва UIDocumentPickerViewController, който предоставя достъп само до избрани от потребителя файлове — iOS не предоставя пълен достъп до файловата система на устройството.
Облачните услуги — iCloud, Google Drive, Dropbox — могат да се интегрират във файловата система на устройството чрез системни доставчици. На iOS iCloud Drive е част от Sandbox контейнера на приложението и файловете автоматично се синхронизират между устройствата на потребителя. На Android Google Drive предоставя API за четене и запис на файлове, но не се осъществява директно монтиране във файловата система. За мобилни приложения, работещи с големи обеми данни, облачното хранилище може да служи като алтернатива на SD картата, особено на устройства без слот за разширение.
Работата с външно хранилище на Android зависи от версията на операционната система и модела Scoped Storage. Процесът на достъп до файлове се различава за Android 9 и по-ниски, Android 10–12 и Android 13+.
От Android 10 основният начин за достъп до общи мултимедийни файлове е MediaStore API. Този API предоставя унифициран интерфейс за четене и запис на изображения, видеоклипове и аудио файлове в общото хранилище. Приложението не изисква разрешение READ_EXTERNAL_STORAGE за достъп до собствените си файлове, но за четене на файлове на други приложения все още е необходимо изрично потребителско разрешение. MediaStore автоматично индексира мултимедийни файлове и предоставя ContentResolver за тяхното запитване.
val collection = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
} else {
MediaStore.Images.Media.EXTERNAL_CONTENT_URI
}
val projection = arrayOf(
MediaStore.Images.Media._ID,
MediaStore.Images.Media.DISPLAY_NAME
)
val cursor = contentResolver.query(collection, projection, null, null, null)
След изпълнение на заявката получавате Cursor, съдържащ URI на файловете. За четене на файла отворете InputStream чрез contentResolver.openInputStream(uri). Записът се извършва аналогично чрез contentResolver.openOutputStream(uri). MediaStore автоматично обработва конфликти на имена и предоставя възможност за вмъкване на нови файлове чрез contentResolver.insert(uri, values), който връща URI на създадения файл.
Storage Access Framework (SAF) — препоръчителният начин за достъп до произволни файлове на Android 10+. SAF предоставя системен диалог за избор на файлове, чрез който потребителят дава на приложението достъп до конкретен файл или директория. Приложението получава URI за достъп, който е валиден до рестартиране на устройството или до изрично оттегляне на разрешението чрез настройките. SAF не изисква разрешения READ_EXTERNAL_STORAGE или WRITE_EXTERNAL_STORAGE, което опростява публикуването в Google Play и намалява броя на заявките за разрешения.
val requestCode = 42
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
intent.addFlags(
Intent.FLAG_GRANT_READ_URI_PERMISSION
or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
)
startActivityForResult(intent, requestCode)
На iOS работата с външни файлове се осъществява чрез UIDocumentPickerViewController, който потребителят отваря за избор на конкретни файлове или директории. Приложението няма пряк достъп до файловата система на външното устройство — само до файловете, които потребителят изрично е избрал. След избора на файл приложението получава временен URL адрес в Sandbox контейнера и може да работи с файла чрез FileManager.
UIDocumentPickerViewController позволява на потребителя да избере един или повече файлове от всеки достъпен източник: iCloud Drive, свързано USB устройство, външна облачна услуга. След избора контролерът връща масив от URL адреси, които приложението може да чете по време на сесията. За запазване на достъпа след затваряне на приложението е необходимо да извикате startAccessingSecurityScopedResource() и да запазите security-scoped отметка в UserDefaults.
let picker = UIDocumentPickerViewController(
forOpeningContentTypes: [.data, .image],
asCopy: true
)
picker.delegate = self
func documentPicker(
controller: UIDocumentPickerViewController,
didPickDocumentsAt urls: [URL]
) {
guard let url = urls.first else { return }
let data = try Data(contentsOf: url)
}
Параметърът asCopy: true означава, че iOS ще копира файла в Sandbox контейнера на приложението и приложението ще получи собствено копие, независимо от оригиналния файл. Ако зададете asCopy: false, приложението получава препратка към оригиналния файл, но за достъп до него трябва да извикате url.startAccessingSecurityScopedResource(). Без това извикване четенето на файла ще предизвика изключение. След приключване на работата с файла задължително извикайте url.stopAccessingSecurityScopedResource(), за да затворите ресурса и да предотвратите изтичане на дескриптори.
Сигурността на външното хранилище е по-ниска от тази на вътрешното, тъй като файловете са достъпни за други приложения. Всяко приложение с разрешение READ_EXTERNAL_STORAGE може да прочете всички файлове на SD картата, включително тези, които вашето приложение е създало за временно съхранение на поверителни данни. Злонамерено приложение може да сканира SD картата и да извлече потребителски данни, ако те не са криптирани. Поради това категорично не се препоръчва съхраняването на токени за удостоверяване, пароли или лични данни на потребителя във външно хранилище в некриптиран вид.
На Android 10+ Scoped Storage значително ограничава възможностите на приложенията за достъп до общата файлова система. Приложението може без разрешение да чете само файлове, създадени от него самото, а за достъп до файлове на други приложения се изисква изрично съгласие на потребителя чрез SAF диалог. Това ограничение обаче не се отнася за приложения с целева версия на SDK под 29 — те продължават да работят по стария модел, което създава риск за потребителите, които не са актуализирали приложенията си. Google Play от 2021 г. изисква targetSdkVersion 29+ за всички нови и актуализирани приложения.
Форматиране и криптиране — друг важен аспект на сигурността. SD карта, форматирана като преносимо хранилище, не се криптира от системата по подразбиране. Дори при използване на adoptable storage, криптирането се активира само ако производителят на устройството е включил тази възможност във фърмуера. За защита на поверителни данни, съхранявани на външно хранилище, използвайте библиотеката EncryptedFile от AndroidX Security, която криптира всеки файл отделно с AES256-GCM, независимо от системното криптиране.
Ефективното използване на външно хранилище изисква баланс между достъпността на данните и сигурността. Спазвайте следните правила за осигуряване на надеждно съхранение на потребителски файлове.
Environment.getExternalStorageState() за проверка на състоянието на SD картата. Картата може да бъде извадена, повредена или недостъпна за записВажно е да помните, че външното хранилище не гарантира запазване на данните при повреди. SD картите имат ограничен ресурс от цикли на презапис, особено бюджетните модели от клас Class 4 и Class 6. При интензивен запис (например логване или кеширане на поточни данни) картата може да се повреди в рамките на няколко месеца. За такива сценарии използвайте вътрешна памет или облачно хранилище, а на външното хранилище съхранявайте само файлове, чиято загуба потребителят смята за приемлива. Редовно проверявайте състоянието на SD картата чрез StatFs и информирайте потребителя за критични грешки на файловата система.
Често задавани въпроси
На Android 13+ разрешението READ_EXTERNAL_STORAGE е заменено с по-гранулирани: READ_MEDIA_IMAGES, READ_MEDIA_VIDEO и READ_MEDIA_AUDIO. За достъп до други типове файлове използвайте SAF.
Да, функцията adoptable storage е достъпна на Android 6.0+. Картата се форматира на ext4 с криптиране AES-128. Въпреки това много производители изключват тази опция и около 88% от устройствата не поддържат adoptable storage.
Използвайте метода Environment.getExternalStorageState(), който връща низ за състоянието. Стойността MEDIA_MOUNTED означава, че картата е достъпна за четене и запис. Други стойности показват грешки или липса на карта.
Scoped Storage ограничава приложението до неговия собствен контейнер и общите медийни библиотеки на MediaStore. Пълният достъп разрешава четене на всякакви файлове на устройството. Scoped Storage повишава сигурността на потребителските данни и е задължителен за нови приложения.
Стартирайте Intent с действие ACTION_OPEN_DOCUMENT_TREE, което отваря системен диалог за избор на директория. След избора ще получите URI разрешение, валидно до рестартиране. Запазете този URI в SharedPreferences за последваща употреба.
Резюме
Ще разработим мобилно приложение под ключ
IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.
Прочетете също