domingo, 8 de febrero de 2015

Como detectar rutas de almacenamiento en Android

En esta entrada vamos a aprender a detectar rutas de almacenamiento en Android,esto puede que se entienda para diversas cosas, a lo que me refiero es encontrar los puntos de montaje de nuestras tarjetas sd o de la memoria interna,ya que muchos dispositivos sean tablets,smartphones tienen rutas distintas,por ejemplo:

/mnt/sdcard

otras

/mnt/sdcard0

etc.

Con la funcion de Environment esta:

Environment.getExternalStorageDirectory();

Nos da solo la externa pero para los dispositivos con mas de una memoria esto se complica.

Esta función no nos da la ruta interna:

Environment.getDataDirectory();
Nos da la ruta data de la aplicación,algo así como:

/data
Y no es lo que queremos en este caso,en este caso es por ejemplo para una aplicaccion multimedia que busca todos los archivos de música,fotos o vídeo y para eso necesitamos los distintos almacenamientos.

Para hacer lo que mencione existe la MediaStore que contempla las rutas pero muchas veces no tiene información completa y se tarda en actualizar en dispositivos antiguos por ejemplo si le acabamos de mandar imagenes por medio de la pc en almacenamiento masivo,así que es mejor buscar la información nosotros mismos.


Bien,la solución que vamos a usar aquí es la siguiente,vamos a buscar en las posibles rutas de montaje de Android y guardar las carpetas que contengan sd ya que en muchos dispositivos así es como lo hace Android,si no es asi tendríamos que añadir otras coincidencias.

Primero que nada vamos a crear un ArrayList de Strings que va a guardar las rutas sd:

private ArrayList SD_CARDS;

Ahora vamos a crear una función que haga el trabajo:



1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
 private ArrayList<String> getAllsds() {
  ArrayList<String> tmp = new ArrayList<String>(); // Array de todas las rutas

  String rutas[] = { "/mnt/", "/storage/" }; // Rutas posibles

  for (int i = 0; i < rutas.length; i++) {
   File file = new File(rutas[i]);// Ruta actual ( listamos de uno a uno )
   if (!file.exists()) // Si no existe pasamos a la siguiente
    continue;
   System.out.println("Ruta : " + rutas[i]); // Imprimimos para "depurar"
   String f[] = file.list(); // Contenido de ruta actual
   for (int o = 0; o < f.length; o++) { // Recorremos el contenido de la ruta actual
    if (f[o].indexOf("sd") != -1) { // Vemos si contiene sd en el nombre si es asi es almacenamiento
     String ruta = rutas[i] + f[o]; // Creamos una Ruta,esta ruta es la original
     File fd = new File(ruta); // Creamos un nuevo File para evitar rutas repetidas basadas en symlinks
     String toAdd;
     try {
      System.out.println("Canocial :"
        + fd.getCanonicalPath().toString()); // Esta seria la ruta original
      toAdd = fd.getCanonicalPath().toString();
     } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
      toAdd = null;
      continue;
     }
     if (!tmp.contains(toAdd)) { // Si se repitiera no lo añadimos
      System.out.println("A añadir :" + toAdd);
      tmp.add(toAdd);
     }
    }
   }
  }

  return tmp; // Regresamos el Array de almacenamientos
 }


Ahora solo debemos llamar la función:

SD_CARDS = getAllsds();

Y listo :D

Las rutas se ven el el Logcat pero vamos a mostrarlo en la aplicación mínima que nos crea Eclipse o Android Studio:

Supongamos que el paquete se llama:

com.itimetux.alamacenamientos

Así debe quedar el MainActivity:



1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
package com.itimetux.alamacenamientos;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;

import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.TextView;

public class MainActivity extends ActionBarActivity {
 private ArrayList<String> SD_CARDS;
 private TextView rutas;
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  rutas = (TextView) findViewById(R.id.textView1);
  SD_CARDS = getAllsds();
  String sd = "";
  for (int i=0;i<SD_CARDS.size();i++)
  {
   sd += SD_CARDS.get(i);
   sd += "\n";
  }
  rutas.setText(sd);
 }

 @Override
 public boolean onCreateOptionsMenu(Menu menu) {
  // Inflate the menu; this adds items to the action bar if it is present.
  getMenuInflater().inflate(R.menu.main, menu);
  return true;
 }

 @Override
 public boolean onOptionsItemSelected(MenuItem item) {
  // Handle action bar item clicks here. The action bar will
  // automatically handle clicks on the Home/Up button, so long
  // as you specify a parent activity in AndroidManifest.xml.
  int id = item.getItemId();
  if (id == R.id.action_settings) {
   return true;
  }
  return super.onOptionsItemSelected(item);
 }

 private ArrayList<String> getAllsds() {
  ArrayList<String> tmp = new ArrayList<String>(); // Array de todas las rutas

  String rutas[] = { "/mnt/", "/storage/" }; // Rutas posibles

  for (int i = 0; i < rutas.length; i++) {
   File file = new File(rutas[i]);// Ruta actual ( listamos de uno a uno )
   if (!file.exists()) // Si no existe pasamos a la siguiente
    continue;
   System.out.println("Ruta : " + rutas[i]); // Imprimimos para "depurar"
   String f[] = file.list(); // Contenido de ruta actual
   for (int o = 0; o < f.length; o++) { // Recorremos el contenido de la ruta actual
    if (f[o].indexOf("sd") != -1) { // Vemos si contiene sd en el nombre si es asi es almacenamiento
     String ruta = rutas[i] + f[o]; // Creamos una Ruta,esta ruta es la original
     File fd = new File(ruta); // Creamos un nuevo File para evitar rutas repetidas basadas en symlinks
     String toAdd;
     try {
      System.out.println("Canocial :"
        + fd.getCanonicalPath().toString()); // Esta seria la ruta original
      toAdd = fd.getCanonicalPath().toString();
     } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
      toAdd = null;
      continue;
     }
     if (!tmp.contains(toAdd)) { // Si se repitiera no lo añadimos
      System.out.println("A añadir :" + toAdd);
      tmp.add(toAdd);
     }
    }
   }
  }

  return tmp; // Regresamos el Array de almacenamientos
 }
}



Así queda la vista xml activity_main.xmll:



1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.itimetux.alamacenamientos.MainActivity" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/textView1"
        android:text="@string/hello_world" />

</RelativeLayout>

Y por ultimo el AndroidManifiest.xml:



1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.itimetux.alamacenamientos"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="21" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    
    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

Ejecutamos:


En otro dispositivo:



Para que funcione el MainActivity tal y como lo coloque aquí necesitan tener instalado el soporte para v7 ActionBarActivity.

Aun asi pueden probar la función getAllsds() independientemente de como sea su aplicacion,solo que necesitan añadir el permiso de acceder al almacenamiento en el AndroidManifiest.xml.

Si existen mas rutas en el futuro o alguna que no contemple tenemos que añadir la ruta aquí:


String rutas[] = { "/mnt/", "/storage/","otra_ruta" }; 

Si existen almacenamientos que ademas de usar el nombre sd usan otro nombre tendríamos que añadir un or así:



if (f[o].indexOf("sd") != -1 || f[o].indexOf("otra_coincidencia") != -1)  { ... }


Eso es todo :D.


No hay comentarios.:

Publicar un comentario

Los comentarios serán revisados antes de ser publicados.