Существует ли универсальный способ определения местоположения внешней SD-карты?
Пожалуйста, не путайте с External Storage .
Environment.getExternalStorageState()
возвращает путь к внутренней точке монтирования SD, например, "/ mnt / sdcard". Но вопрос по поводу внешнего SD. Как мне получить путь типа "/ mnt / sdcard / external_sd" (он может отличаться от устройства к устройству)?
Я думаю, я закончу фильтрацией вывода mount
команды по имени файловой системы. Но я не уверен, что этот способ достаточно надежен.
Ответы:
Нет,
Environment.getExternalStorageDirectory()
относится к тому, что производитель устройства считает «внешним хранилищем». На некоторых устройствах это съемный носитель, например SD-карта. На некоторых устройствах это часть флэш-памяти на устройстве. Здесь «внешнее хранилище» означает «содержимое, доступное через режим USB Mass Storage при подключении к хост-машине», по крайней мере для Android 1.x и 2.x.Android не имеет понятия «внешняя SD», кроме внешнего хранилища, как описано выше.
Если производитель устройства выбрал встроенную флэш-память, а также имеет SD-карту, вам необходимо связаться с этим производителем, чтобы определить, можете ли вы использовать SD-карту (не гарантировано) и для чего нужны правила. используя его, например, какой путь использовать для него.
ОБНОВИТЬ
Две последние заметки:
Во-первых, в Android 4.4+ у вас нет доступа для записи на съемный носитель (например, «внешний SD»), за исключением любых мест на этом носителе, которые могут быть возвращены
getExternalFilesDirs()
иgetExternalCacheDirs()
. Посмотрите превосходный анализ Дейва Смита , особенно если вы хотите получить детали низкого уровня.Во-вторых, чтобы никто не спорил о том, является ли доступ к съемным носителям иным образом частью Android SDK, вот оценка Дайан Хакборн :
источник
Я нашел следующее решение, основанное на некоторых ответах, найденных здесь.
КОД:
ИСПОЛЬЗОВАНИЕ:
источник
У меня было приложение, в
ListPreference
котором пользователь должен был выбрать место, где он хотел что-то сохранить.В этом приложении я сканировал
/proc/mounts
и/system/etc/vold.fstab
точки подключения SDCard. Я сохранил точки монтирования из каждого файла в два отдельных файлаArrayList
.Затем я сравнил один список с другим и отбросил элементы, которых не было в обоих списках. Это дало мне список корневых путей к каждой SDCard.
Оттуда, я проверил пути с
File.exists()
,File.isDirectory()
иFile.canWrite()
. Если какой-либо из этих тестов был ложным, я исключил этот путь из списка.Все, что осталось в списке, я преобразовал в
String[]
массив, чтобы он мог использоватьсяListPreference
атрибутом values.Вы можете просмотреть код здесь: http://sapienmobile.com/?p=204
источник
Вы можете попробовать использовать вспомогательную библиотечную функцию под названием ContextCompat.getExternalFilesDirs () :
Первый - это первичное внешнее хранилище, а остальные должны быть настоящими путями SD-карт.
Причина множественного ".getParentFile ()" состоит в том, чтобы перейти в другую папку, так как исходный путь
РЕДАКТИРОВАТЬ: вот более всеобъемлющий способ, который я создал, чтобы получить пути SD-карт:
источник
App
,ContextCompact
,EnvironmentCompact
Чтобы извлечь все внешние хранилища (будь то SD-карты или внутренние несъемные хранилища ), вы можете использовать следующий код:
В качестве альтернативы вы можете использовать System.getenv («EXTERNAL_STORAGE») для извлечения основного каталога внешнего хранилища (например, «/ storage / sdcard0» ) и System.getenv («SECONDARY_STORAGE») для получения списка всех вторичных каталогов (например, « / storage / extSdCard: / storage / UsbDriveA: / storage / UsbDriveB " ). Помните, что и в этом случае вам может потребоваться отфильтровать список вторичных каталогов, чтобы исключить USB-накопители.
В любом случае, обратите внимание, что использование жестко закодированных путей - это всегда плохой подход (особенно, когда каждый производитель может изменить его по своему усмотрению).
источник
System.getenv("SECONDARY_STORAGE")
может также относиться к некоторым ссылкам, так как он кажется недокументированным./mnt
нем могут быть и другие fs-деревья, а не только SD-карты и USB-накопители. Ваш код также будет перечислять любые внутренние (возможно, даже виртуальные) монтирования файловой системы, если я правильно понимаю, в то время как вопрос требует только sdcards .Как и Ричард, я также использую файл / proc / mounts для получения списка доступных опций хранения
источник
printStackTrace
? Когда у нас естьandroid.util.Log.e
?Можно найти, где монтируются любые дополнительные SD-карты, читая
/proc/mounts
(стандартный файл Linux) и сверяясь с данными vold (/system/etc/vold.conf
). И обратите внимание, что возвращаемое местоположениеEnvironment.getExternalStorageDirectory()
может не отображаться в конфигурации vold (на некоторых устройствах это внутреннее хранилище, которое не может быть отключено), но все равно должно быть включено в список. Однако мы не нашли хорошего способа описать их пользователю .источник
mount
более совместимо, чем чтение/proc
файловой системы. Проблема в том, что SD-карта не обязательно отформатирована как FAT. Кроме того, точка монтирования карты может варьироваться от ПЗУ к ПЗУ. Кроме того, может быть несколько других разделов VFAT ...mount
исполняемого файла, тем более что запуск исполняемых файлов не рекомендуется.Я пробую все решения в этой теме на этот раз. Но все они не работали правильно на устройствах с одной внешней (съемной) и одной внутренней (несъемной) платами. Путь к внешней карте невозможно получить из команды 'mount', из файла 'proc / mounts' и т. Д.
И я создаю свое собственное решение (для Пауло Луана):
источник
Если вы посмотрите на исходный код,
android.os.Environment
вы увидите, что Android сильно зависит от переменных среды для путей. Вы можете использовать переменную окружения "SECONDARY_STORAGE", чтобы найти путь к съемной SD-карте.Пример использования:
источник
Просто используйте это:
источник
SECONDARY_STORAGE
есть несколько путей, разделенных двоеточием (":"). Вот почему я разделил строку (см. Мой ответ выше).К универсальному способу , если вы имеете в виду официальный пути; да, есть один
На уровне API 19, то есть в Android версии 4.4 Kitkat, они добавили
File[] getExternalFilesDirs (String type)
вContext
класс, который позволяет приложениям хранить данные / файлы на картах Micro SD.Android 4.4 - это первая версия платформы, которая позволила приложениям использовать SD-карты для хранения. Любой доступ к SD-картам до уровня API 19 осуществлялся через частные неподдерживаемые API.
getExternalFilesDirs (тип String) возвращает абсолютные пути к каталогам приложений для всех общих / внешних устройств хранения. Это означает, что он вернет пути к внутренней и внешней памяти. Как правило, второй возвращаемый путь - это путь к карте памяти microSD (если есть).
Но учтите, что
Терминология внутреннего и внешнего хранилища в соответствии с Google / официальной документацией по Android сильно отличается от того, что мы думаем.
источник
getExternalFilesDirs()
часто возвращает SD-карты, которые не являются съемными, поэтому нет, это не универсальный способ найти местоположение съемной SD-карты.Вот способ, которым я использую, чтобы найти внешнюю карту. Используйте команду mount cmd return, а затем проанализируйте часть vfat.
источник
Это решение учитывает тот факт, что
System.getenv("SECONDARY_STORAGE")
бесполезно с Зефир.Протестировано и работает над:
Samsung Galaxy Tab A (Android 6.0.1 - сток)
источник
Поскольку мой оригинальный ответ выше, сканирование vold больше не подходит для разных производителей.
Я разработал более надежный и простой метод.
Корни будут содержать все доступные для записи корневые каталоги в системе, включая любые USB-подключенные USB-устройства.
ПРИМЕЧАНИЕ. Для метода canWrite требуется разрешение android.permission.WRITE_EXTERNAL_STORAGE.
источник
/external_sd
это внешняя карта microSD; на некоторых LG это/_ExternalSD
; на некоторых устройствах это/sdcard
. Может быть, последняя является символической ссылкой/storage/sdcard0
или похожей, но будут ли эти другие действительно надежно защищены/storage/*
и/mount/*
?pathname.canWrite()
и требовать разрешения WRITE_EXTERNAL_STORAGE? Почему бы просто не позвонитьpathname.canRead()
?было так поздно, но, наконец, у меня появилось кое-что, что я проверил на большинстве устройств (по производителям и версиям для Android), работающих на Android 2.2+. если вы обнаружите, что он не работает, прокомментируйте его с именем вашего устройства. я починю это. если кому-то интересно, я объясню, как это работает.
источник
Написав код ниже, вы получите местоположение:
/ Хранение / 663D-554E / Android / данные / app_package_name / файлы /
который хранит данные вашего приложения в / android / data location внутри sd_card.
Я тестировал этот код на устройстве moto g4 plus и Samsung (все работает нормально).
надеюсь, что это может быть полезным.
источник
Вот метод, который я использую, чтобы найти съемный SD-карту. Это сложно, и, возможно, в некоторых ситуациях это излишне, но работает на самых разных версиях Android и производителях устройств, которые я тестировал за последние несколько лет. Я не знаю ни одного устройства с уровня API 15, на котором он не находит SD-карту, если она установлена. В большинстве случаев он не возвращает ложных срабатываний, особенно если вы даете ему имя известного файла для поиска.
Пожалуйста, дайте мне знать, если вы столкнетесь с какими-либо случаями, когда это не работает.
PS
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
в манифесте. А на уровне API 23 и выше обязательно используйтеcheckSelfPermission
/requestPermissions
.findSdCardPath(),
а не пересчитывать его каждый раз, когда вам это нужно.Log.d()
приведенном выше коде есть куча logging ( ). Это помогает диагностировать любые случаи, когда правильный путь не найден. Прокомментируйте это, если вы не хотите регистрироваться.источник
Единственное рабочее решение, которое я нашел, было это, которое использует отражение
источник
Я не знаю почему, но мне нужно вызвать .createNewFile () для файла, созданного в каталогах общего хранилища, прежде чем его использовать. В рамках комментария к этому методу говорится, что он бесполезен. Вот образец ...
источник
Я создал метод utils, чтобы проверить, доступна ли SD-карта на устройстве или нет, и получить путь SD-карты на устройстве, если она доступна.
Вы можете скопировать 2 метода ниже в класс вашего проекта, который вам нужен. Вот и все.
источник
Он работает для всех внешних устройств, но убедитесь, что вы получаете только имя папки внешнего устройства, а затем вам нужно получить файл из заданного местоположения, используя класс File.
Вызов:
Получение доступа к внешнему хранилищу
Для чтения или записи файлов на внешнее хранилище ваше приложение должно получить системные разрешения READ_EXTERNAL_STORAGE или WRITE_EXTERNAL_STORAGE . Например:
источник
/ sdcard => Внутреннее хранилище (это символическая ссылка, но она должна работать)
/ mnt / extSdCard => Внешняя SDCard
Это для Samsung Galaxy S3
Вы, вероятно, можете рассчитывать на то, что это верно для большинства ... однако дважды проверьте!
источник
/sdcard
это символическая ссылка на внешний на моем Sony 2305.