2011-05-27 5 views
5

Algunas tabletas Android 2.x, como HTC Flyer y Samsung Galaxy Tab, admiten el almacenamiento interno de la tableta y una tarjeta SD externa. Por ejemplo, en mi Flyer, /sdcard y /sdcard2 están separados, y el primero representa el "almacenamiento interno" de la tableta.¿Existe una forma documentada, en Android 2.x, de inspeccionar varias tarjetas SD para ver el contenido?

Si uso Environment.getExternalStorageDirectory(), no parece haber ninguna regla para saber que será devuelto de esos lugares de almacenamiento. Al usar getExternalStorageDirectory(), me preocupa que solo encuentre medios almacenados en una de las dos ubicaciones de almacenamiento.

Una solución es simplemente la exploración /sdcard* difícil que el código en la aplicación, pero esto hace la suposición de que todos los dispositivos usar eso como un esquema de nombres, y no considero que una suposición segura.

¿Existe alguna manera documentada de escanear y usar varias ubicaciones de tarjeta/almacenamiento sd en Android 2.x?

Mi objetivo es en realidad para encontrar todos los libros de audio en la tableta, así que me gustaría encontrar y utilizar todos /sdcard*/Audiobooks de alguna manera documentada.

Respuesta

3

Normalmente, la segunda tarjeta sd se monta dentro de la primera.

Esto es lo que quiero decir:

  • Primera sdcard está montado en /mnt/sdcard.

  • El segundo sdcard se monta en /mnt/sdcard/external_sd

Así que cada vez que recibe /mnt/sdcard como camino para almacenamiento externo y comenzar a escanear el árbol, que no se pierda la segunda tarjeta sd (si también se montó) .

Esto no es comportamiento documentado. Pero Galaxy Tab se comporta exactamente de esta manera. Supongo que esto se debe a que no hay soporte oficial para Android API (es decir, no hay una función especial en la clase Environment) para múltiples almacenamientos externos.

+0

Aha! Noté que/sdcard y/sdcard2 existen, pero no vi en adb que/sdcard2 apuntaba a/mnt/sdcard/ext_sd. ¡Gracias! –

+1

Quiero reiterar lo que dijo; esto no está documentado, y no es estándar. Algunos fabricantes de dispositivos hacen esto. Algunos no. No puede contar con que se haga de esa manera, no puede contar con que el nombre de ese directorio sea consistente, etc. Actualmente, no hay una API estándar en la plataforma para esto. – hackbod

+0

Sí, tienes razón. El nombre del directorio puede ser diferente en diferentes dispositivos. Pero los proveedores se ven obligados a colocar la segunda carpeta de tarjeta SD dentro de la primera carpeta de tarjeta SD para habilitar la compatibilidad con ambas tarjetas SD en aplicaciones que no conocen esa segunda tarjeta sd. Así que, básicamente, es seguro confiar en el hecho de que hay un directorio sdcard externo (incluso si se combinan dos o más sdcards físicas). – inazaruk

1

Puede usar el código de abajo para obtener rutas a todas las tarjetas SD en el sistema. Esto funciona en todas las versiones de Android y rutas de retorno a todos los almacenes (incluido el emulado).

Funciona correctamente en todos mis dispositivos.

private static final Pattern DIR_SEPORATOR = Pattern.compile("/"); 

/** 
* Raturns all available SD-Cards in the system (include emulated) 
* 
* Warning: Hack! Based on Android source code of version 4.3 (API 18) 
* Because there is no standart way to get it. 
* TODO: Test on future Android versions 4.4+ 
* 
* @return paths to all available SD-Cards in the system (include emulated) 
*/ 
public static String[] getStorageDirectories() 
{ 
    // Final set of paths 
    final Set<String> rv = new HashSet<String>(); 
    // Primary physical SD-CARD (not emulated) 
    final String rawExternalStorage = System.getenv("EXTERNAL_STORAGE"); 
    // All Secondary SD-CARDs (all exclude primary) separated by ":" 
    final String rawSecondaryStoragesStr = System.getenv("SECONDARY_STORAGE"); 
    // Primary emulated SD-CARD 
    final String rawEmulatedStorageTarget = System.getenv("EMULATED_STORAGE_TARGET"); 
    if(TextUtils.isEmpty(rawEmulatedStorageTarget)) 
    { 
     // Device has physical external storage; use plain paths. 
     if(TextUtils.isEmpty(rawExternalStorage)) 
     { 
      // EXTERNAL_STORAGE undefined; falling back to default. 
      rv.add("/storage/sdcard0"); 
     } 
     else 
     { 
      rv.add(rawExternalStorage); 
     } 
    } 
    else 
    { 
     // Device has emulated storage; external storage paths should have 
     // userId burned into them. 
     final String rawUserId; 
     if(Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) 
     { 
      rawUserId = ""; 
     } 
     else 
     { 
      final String path = Environment.getExternalStorageDirectory().getAbsolutePath(); 
      final String[] folders = DIR_SEPORATOR.split(path); 
      final String lastFolder = folders[folders.length - 1]; 
      boolean isDigit = false; 
      try 
      { 
       Integer.valueOf(lastFolder); 
       isDigit = true; 
      } 
      catch(NumberFormatException ignored) 
      { 
      } 
      rawUserId = isDigit ? lastFolder : ""; 
     } 
     // /storage/emulated/0[1,2,...] 
     if(TextUtils.isEmpty(rawUserId)) 
     { 
      rv.add(rawEmulatedStorageTarget); 
     } 
     else 
     { 
      rv.add(rawEmulatedStorageTarget + File.separator + rawUserId); 
     } 
    } 
    // Add all secondary storages 
    if(!TextUtils.isEmpty(rawSecondaryStoragesStr)) 
    { 
     // All Secondary SD-CARDs splited into array 
     final String[] rawSecondaryStorages = rawSecondaryStoragesStr.split(File.pathSeparator); 
     Collections.addAll(rv, rawSecondaryStorages); 
    } 
    return rv.toArray(new String[rv.size()]); 
} 
Cuestiones relacionadas