¿Existe una forma universal de encontrar la ubicación de una tarjeta SD externa?
Por favor, no se confunda con el almacenamiento externo .
Environment.getExternalStorageState()
devuelve la ruta al punto de montaje SD interno, como "/ mnt / sdcard". Pero la pregunta es sobre la SD externa. ¿Cómo obtengo una ruta como "/ mnt / sdcard / external_sd" (puede diferir de un dispositivo a otro)?
Supongo que terminaré con el filtrado de la salida del mount
comando por nombre de sistema de archivos. Pero no estoy seguro de que esta manera sea lo suficientemente robusta.
Respuestas:
No, se
Environment.getExternalStorageDirectory()
refiere a lo que el fabricante del dispositivo considera "almacenamiento externo". En algunos dispositivos, este es un medio extraíble, como una tarjeta SD. En algunos dispositivos, esta es una parte del flash del dispositivo. Aquí, "almacenamiento externo" significa "las cosas accesibles a través del modo de almacenamiento masivo USB cuando se monta en una máquina host", al menos para Android 1.xy 2.x.Android no tiene el concepto de "SD externo", aparte del almacenamiento externo, como se describió anteriormente.
Si el fabricante de un dispositivo ha elegido que el almacenamiento externo sea flash incorporado y también tenga una tarjeta SD, deberá ponerse en contacto con ese fabricante para determinar si puede usar la tarjeta SD (no garantizada) y cuáles son las reglas para usándolo, como qué ruta usar para él.
ACTUALIZAR
Dos cosas recientes de nota:
Primero, en Android 4.4+, no tiene acceso de escritura a medios extraíbles (p. Ej., "SD externo"), a excepción de cualquier ubicación en ese medio que pueda ser devuelta por
getExternalFilesDirs()
ygetExternalCacheDirs()
. Vea el excelente análisis de Dave Smith sobre esto, especialmente si desea los detalles de bajo nivel.En segundo lugar, para que nadie cuestione si el acceso a medios extraíbles es o no parte del SDK de Android, aquí está la evaluación de Dianne Hackborn :
fuente
Se me ocurrió la siguiente solución basada en algunas respuestas encontradas aquí.
CÓDIGO:
USO:
fuente
Tenía una aplicación que usaba un lugar
ListPreference
donde el usuario debía seleccionar la ubicación donde deseaba guardar algo.En esa aplicación, escaneé
/proc/mounts
y en/system/etc/vold.fstab
busca de puntos de montaje de tarjeta SD. Almacené los puntos de montaje de cada archivo en dos correos separadosArrayList
.Luego, comparé una lista con la otra y descarté elementos que no estaban en ambas listas. Eso me dio una lista de rutas raíz para cada tarjeta SD.
A partir de ahí, he probado con los caminos
File.exists()
,File.isDirectory()
yFile.canWrite()
. Si alguna de esas pruebas era falsa, descarté esa ruta de la lista.Lo que quedaba en la lista, lo convertí a una
String[]
matriz para que pudiera ser utilizado por elListPreference
atributo de valores.Puede ver el código aquí: http://sapienmobile.com/?p=204
fuente
Puede intentar usar la función de biblioteca de soporte llamada ContextCompat.getExternalFilesDirs () :
El primero es el almacenamiento externo primario, y el resto se supone que son rutas de tarjetas SD reales.
La razón del múltiple ".getParentFile ()" es subir otra carpeta, ya que la ruta original es
EDITAR: aquí hay una forma más completa que he creado, para obtener las rutas de las tarjetas SD:
fuente
App
,ContextCompact
,EnvironmentCompact
Para recuperar todos los almacenamientos externos (ya sean tarjetas SD o almacenamientos internos no extraíbles ), puede usar el siguiente código:
Alternativamente, puede usar System.getenv ("EXTERNAL_STORAGE") para recuperar el directorio primario de almacenamiento externo (por ejemplo, "/ storage / sdcard0" ) y System.getenv ("SECONDARY_STORAGE") para recuperar la lista de todos los directorios secundarios (por ejemplo, " / storage / extSdCard: / storage / UsbDriveA: / storage / UsbDriveB " ). Recuerde que, también en este caso, es posible que desee filtrar la lista de directorios secundarios para excluir las unidades USB.
En cualquier caso, tenga en cuenta que el uso de rutas codificadas siempre es un mal enfoque (especialmente cuando cada fabricante puede cambiarlo a su gusto).
fuente
System.getenv("SECONDARY_STORAGE")
también podría hacer con algunas referencias, ya que parece indocumentado./mnt
también puede haber varios otros árboles fs, no solo tarjetas SD y unidades USB. Su código también enumeraría cualquier montaje interno (quizás incluso virtual) del sistema de archivos, si lo entiendo bien, mientras que la pregunta solo quiere tarjetas SD .Al igual que Richard, también uso el archivo / proc / mounts para obtener la lista de opciones de almacenamiento disponibles.
fuente
printStackTrace
? Cuando tenemosandroid.util.Log.e
?Es posible encontrar dónde se montan las tarjetas SD adicionales mediante la lectura
/proc/mounts
(archivo estándar de Linux) y la verificación cruzada con datos vold (/system/etc/vold.conf
). Y tenga en cuenta que la ubicación devuelta porEnvironment.getExternalStorageDirectory()
puede no aparecer en la configuración vold (en algunos dispositivos es el almacenamiento interno que no se puede desmontar), pero aún debe incluirse en la lista. Sin embargo, no encontramos una buena manera de describirlos al usuario .fuente
mount
es más compatible que la lectura del/proc
sistema de archivos. El problema es que la tarjeta SD no está necesariamente formateada como FAT. Además, el punto de montaje de la tarjeta puede variar de ROM a ROM. Además, podría haber varias otras particiones VFAT ...mount
ejecutable, especialmente porque se desaconseja el lanzamiento de ejecutables.Intento todas las soluciones dentro de este tema en este momento. Pero todos ellos no funcionaron correctamente en dispositivos con una tarjeta externa (extraíble) y una interna (no extraíble). No es posible obtener la ruta de la tarjeta externa desde el comando 'mount', desde el archivo 'proc / mounts', etc.
Y creo mi propia solución (en la de Paulo Luan):
fuente
Si observa el código fuente
android.os.Environment
, verá que Android depende en gran medida de las variables de entorno para las rutas. Puede usar la variable de entorno "SECONDARY_STORAGE" para encontrar la ruta a la tarjeta SD extraíble.Ejemplo de uso:
fuente
Simplemente use esto:
fuente
SECONDARY_STORAGE
tiene varias rutas separadas con dos puntos (":"). Es por eso que dividí la cadena (ver mi respuesta más arriba).Por vía universal , si te refieres a vía oficial; sí hay una.
En el nivel API 19, es decir, en Android versión 4.4 Kitkat, se han agregado
File[] getExternalFilesDirs (String type)
en laContext
clase que permite a las aplicaciones almacenar datos / archivos en tarjetas micro SD.Android 4.4 es la primera versión de la plataforma que realmente ha permitido que las aplicaciones usen tarjetas SD para almacenamiento. Cualquier acceso a las tarjetas SD antes del nivel de API 19 se realizó a través de API privadas no compatibles.
getExternalFilesDirs (tipo de cadena) devuelve rutas absolutas a directorios específicos de la aplicación en todos los dispositivos de almacenamiento externo / compartido. Significa que devolverá rutas a la memoria interna y externa. Generalmente, el segundo camino devuelto sería la ruta de almacenamiento para la tarjeta microSD (si la hubiera).
Pero ten en cuenta que,
La terminología de almacenamiento interno y externo según Google / documentos oficiales de Android es bastante diferente de lo que pensamos.
fuente
getExternalFilesDirs()
a menudo devuelve tarjetas SD que no son extraíbles, así que no, esta no es una forma universal de encontrar la ubicación de una tarjeta SD extraíble.Aquí está la forma en que uso para encontrar la tarjeta externa. Use mount cmd return y luego analice la parte vfat.
fuente
Esta solución maneja el hecho de que
System.getenv("SECONDARY_STORAGE")
no sirve para nada con Marshmallow.Probado y trabajando en:
Samsung Galaxy Tab A (Android 6.0.1 - Stock)
fuente
Desde mi respuesta original anterior, el escaneo vold ya no es viable en los distintos fabricantes.
He desarrollado un método más confiable y directo.
Las raíces contendrán todos los directorios raíz que se pueden escribir en el sistema, incluidos los dispositivos USB conectados por USB.
NOTA: El método canWrite necesita el permiso android.permission.WRITE_EXTERNAL_STORAGE.
fuente
/external_sd
es la tarjeta microSD externa; en algunos LG, es/_ExternalSD
; en algunos dispositivos lo es/sdcard
. Tal vez este último sea un enlace simbólico/storage/sdcard0
o similar, pero ¿estos otros realmente estarán cubiertos de forma confiable por/storage/*
y/mount/*
?pathname.canWrite()
y requerir el permiso WRITE_EXTERNAL_STORAGE? ¿Por qué no solo llamarpathname.canRead()
?fue muy tarde, pero finalmente obtuve algo que he probado en la mayoría de los dispositivos (por fabricante y versiones de Android) que funciona en Android 2.2+. si encuentra que no funciona, coméntelo con el nombre de su dispositivo. yo lo arreglare. Si alguien interesado explicaré cómo funciona.
fuente
Al escribir el siguiente código obtendrá la ubicación:
/ storage / 663D-554E / Android / data / app_package_name / files /
que almacena los datos de su aplicación en / android / data location dentro de la tarjeta sd_card.
He probado este código en un moto g4 plus y un dispositivo Samsung (todo funciona bien).
Espero que esto pueda ser útil.
fuente
Aquí está el método que uso para encontrar una tarjeta SD extraíble . Es complejo y probablemente exagerado en algunas situaciones, pero funciona en una amplia variedad de versiones de Android y fabricantes de dispositivos que he probado en los últimos años. No conozco ningún dispositivo desde el nivel 15 de API en el que no encuentra la tarjeta SD, si hay una montada. No devolverá falsos positivos en la mayoría de los casos, especialmente si le da el nombre de un archivo conocido para buscar.
Avíseme si se encuentra con algún caso en el que no funciona.
PD
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
en el manifiesto. Y en el nivel API 23 y superior, asegúrese de usarcheckSelfPermission
/requestPermissions
.findSdCardPath(),
lugar de calcularlo cada vez que lo necesite.Log.d()
) en el código anterior. Ayuda a diagnosticar cualquier caso en el que no se encuentre el camino correcto. Comenta si no quieres iniciar sesión.fuente
La única solución de trabajo que encontré fue esta que usa reflexión
fuente
No sé por qué, pero necesito llamar a .createNewFile () en un archivo creado en los directorios de almacenamiento público antes de usarlo. En el marco, los comentarios para ese método dicen que no es útil. Aquí hay una muestra ...
fuente
He creado un método de utilidades para verificar que una tarjeta SD esté disponible en el dispositivo o no, y obtener la ruta de la tarjeta SD en el dispositivo si está disponible.
Puede copiar 2 métodos a continuación en la clase de su proyecto que necesite. Eso es todo.
fuente
Funciona para todos los dispositivos externos, pero asegúrese de obtener solo el nombre de la carpeta del dispositivo externo y luego debe obtener el archivo de la ubicación dada usando la clase File.
Vocación:
Obtener acceso a almacenamiento externo
Para leer o escribir archivos en el almacenamiento externo, su aplicación debe adquirir los permisos del sistema READ_EXTERNAL_STORAGE o WRITE_EXTERNAL_STORAGE . Por ejemplo:
fuente
/ sdcard => Almacenamiento interno (es un enlace simbólico pero debería funcionar)
/ mnt / extSdCard => Tarjeta SD externa
Esto es para Samsung Galaxy S3
Probablemente pueda confiar en que esto sea cierto para la mayoría ... ¡sin embargo, verifique dos veces!
fuente
/sdcard
es un enlace simbólico a externo en mi sony 2305.