Copiar archivo a la tarjeta sd [Android]

overking

Hola, tengo un pequeño problemilla, que parecerá una chorrada, pero estoy atascado y no hay manera.

El caso es que utilizo mapview para mostrar un mapa offline, previamente descargado. Se utilizad una librería para mostrar los mapas offline de osm etc.

El codigo que muestra el mapa es el siguiente:

public class uno extends MapActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        MapView mapView = new MapView(this);
        mapView.setClickable(true);
        mapView.setBuiltInZoomControls(true);
        mapView.setMapFile(new File("/sdcard/mapa.map"));
        setContentView(mapView);
    }
}

Coge el mapa de la sd, porque de asserts o res/raw no funciona. Lo que quiero es que al iniciar la aplicación me copie el mapa a la sd/data/miaplicacion.

La respuesta que me dan en el dev de la librería en cuestión es vaga: https://groups.google.com/group/mapsforge-dev/browse_thread/thread/b022652a665e0968?hl=en

http://www.google.com/url?sa=D&q=http://androideity.com/2011/11/03/escribiendo-archivos-en-la-memoria-externa-sd-card/&usg=AFQjCNHVdz8--f4aSyOByQb7rlHGEVc-_g esto copia un texto y no sé como hacer para que copie el archivo.

Aquí hay una solución, pero no me funciona, me tirar error la aplicación...

http://stackoverflow.com/questions/4447477/android-how-to-copy-files-in-assets-to-sdcard

private void CopyAssets() {
    AssetManager assetManager = getAssets();
    String[] files = null;
    try {
        files = assetManager.list("");
    } catch (IOException e) {
        Log.e("tag", e.getMessage());
    }
    for(String filename : files) {
        InputStream in = null;
        OutputStream out = null;
        try {
          in = assetManager.open(filename);
          out = new FileOutputStream("/sdcard/" + filename);
          copyFile(in, out);
          in.close();
          in = null;
          out.flush();
          out.close();
          out = null;
        } catch(Exception e) {
            Log.e("tag", e.getMessage());
        }       
} } private void copyFile(InputStream in, OutputStream out) throws IOException { byte[] buffer = new byte[1024]; int read; while((read = in.read(buffer)) != -1){ out.write(buffer, 0, read); } }

A ver si alguien me puede echar una manita...

Fr4nk0

Has probado a usar la clase Environment para obtener el directorio de almacenamiento de tu aplicación?

public  static File GetSDDir()
  {
    return Environment.getExternalStorageDirectory();
  }

Lo mismo puede estar el problema en que no tienes permisos para escribir en el directorio que pusiste, que a veces pasa.

Acuerdate también de darle permisos en el manifest

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

PD: No soy un máquina en Android pq estoy empezando muy lentamente, mas leer que hacer por ahora, pero ya he leido casos de error de este tipo.

1 1 respuesta
overking

#2 los permisos los tengo dados, y lo del directorio, bueno, primero quiero conseguir que se copie el maldito archivo, si eso después ya lo coloco bien.

Gracias.

Tig

Este es un código que hice para copiar Assets


  public static File copyAsset(final Context context, final String outFilePath, final String fileName) {
    AssetManager assetManager = context.getAssets();

InputStream in = null;
OutputStream out = null;  
try {
  in = assetManager.open(fileName);
  out = new FileOutputStream(outFilePath);
  copyFile(in, out);
  in.close();
  in = null;
  out.flush();
  out.close();
  out = null;

  File outFile = new File(outFilePath);

  if(outFile.exists()){
    return outFile;
  }
} catch(Exception e) {
  Log.e("tag", e.getMessage());
}

return null;
  }

  public static void copyFile(InputStream in, OutputStream out) throws IOException {
    byte[] buffer = new byte[1024];
    int read;
    while((read = in.read(buffer)) != -1){
      out.write(buffer, 0, read);
    }
  }

No está muy depurado porque al final no lo usé, pero funcionaba. Asegúrate de que el fichero de salida existe, tuve problemas porque Android no se quejaba y simplemente no lo escribía.

Y recuerda, siempre que hagas I/O, hazlo en un Thread aparte.

1
overking

A ver, es que no entiendo muy bien que es lo que hay que hacer. Llevo programando en android 3 días (literal) y creo que quiero abarcar mucho.

Yo tengo mi public class nombre { y aquí llamo al final al copyassets}

y debajo tengo mi private void CopyAssets()

Y claro, tu código es public static y no sé cual es el lugar donde ponerlo.

P.D.: he leído que si pongo el archivo en raw igual es más fácil con

InputStream fIn = this.context.getResources().openRawResource(miarchivo);

Tig

Si el mapa es siempre el mismo, tiene más sentido que lo leas desde assets o en raw. Si puede cambiar, tendrás que meterlo en el almacenamiento externo del teléfono. No he trabajado con mapas cacheados.

Mi código es para meter en una clase de utilidades, de manera que puedes invocarlo desde una actividad

Utils.copyAsset(this,"/mnt/sdcard/.../map.map","mapTiles.tiles")

Si funciona, te devolverá una instancia de File apuntando a "/mnt/sdcard/.../map.map"

Ideas a probar:

  • Que lees bien el fichero
  • Lee bien el fichero de assets e intenta no copiarlo a la SD. Se hace con AssetsManager.
  • Ya tienes como leerlo desde Raw
1 respuesta
overking

#6 En realidad el mapa es siempre el mismo y no varía, es solo una visualización de lo que yo quiero.

1 respuesta
Tig

#7 Entonces intenta leerlo desde assets, pero usa AssetsManager en vez de File.

1 respuesta
overking

#8

Vale, hago lo siguiente, porque según esto http://stackoverflow.com/questions/8474821/how-to-get-the-android-path-string-to-a-file-on-assets-folder no vale con abrirlo nada más.

InputStream is = getAssets().open("mapa.map");
          int size = is.available();
          byte[] buffer = new byte[size];
          is.read(buffer);
          is.close();


      FileOutputStream fos = new FileOutputStream(f);
      fos.write(buffer);
      fos.close();
    } catch (Exception e) { throw new RuntimeException(e); }

Pero al abrir el mapa:

[code]    mapView.setMapFile(f.getPath());[/code]

Me dice que no es aplicable para strings...

Voy a ver si me ayudan allí que parece que saben un taco de esto. Si no le dan por el culo al mapa xd

Tig

Te falta la base de programar java xD

getPath te devuelve un String, y seguro que setMapFile necesita un archivo File. Busca en la documentación dónde debe estar ese File, que igual hay alguna limitación.

1 respuesta
overking

#10 me falta base de java, eso es más que evidente, pero ahora la culpa no es mía porque es la solución que he visto en stackoverflow...

:X

overking

bueh, pues no lo he conseguido, dejaré la aplicación sin map y cuando tenga más tiempo estudiaré un poco de java xd

overking

Esto debería funcionar no?

Pues no


public class CopyActivity extends Activity {
	
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    requestWindowFeature(Window.FEATURE_NO_TITLE); 
    setContentView(R.layout.main);
    
    CopyAssets();

}
   
private void CopyAssets() { AssetManager assetManager = getAssets(); String[] files = null; try { files = assetManager.list(""); } catch (IOException e) { Log.e("tag", e.getMessage()); } for(String filename : files) { InputStream in = null; OutputStream out = null; try { in = assetManager.open(filename); out = new FileOutputStream("/sdcard/" + filename); copyFile(in, out); in.close(); in = null; out.flush(); out.close(); out = null; } catch(Exception e) { Log.e("tag", e.getMessage()); } } } private void copyFile(InputStream in, OutputStream out) throws IOException { byte[] buffer = new byte[1024]; int read; while((read = in.read(buffer)) != -1){ out.write(buffer, 0, read); } } }
Tig

1) ¿Qué hay dentro de tu directorio assets?

2) ¿Seguro que la ruta /sdcard existe en tu teléfono/emulador? Puedes entrar al teléfono ejecutando "adb shell", y prueba a entrar al directorio /sdcard, a ver si existe (que sí debería existir, sólo para asegurarnos)

3) ¿No salta ninguna excepción?

4) ¿Tienes permisos para escribir en /sdcard? Supongo que sí, porque si no peta

¿Qué librería de mapas estás usando? ¿Open Street Maps? Parece que aquí hay alguien que tuvo un problema similar, aunque la respuesta dice que hay que hacer lo que estás intentando

http://stackoverflow.com/questions/8476452/how-to-get-the-android-string-path-to-a-file-on-drawable-folder

¿Tienes link al api de la librería?

1 respuesta
overking

#14 muchas gracias :D, me estaba volviendo loco, y lo que pasa es que android comprime los archivos de la carpeta assets y después no funcionan.

Solución, en vez extensión .map le he puesto extensión mp3, y ya funciona.

De todas formas el código anterior no funciona, luego pongo el bueno.

Usuarios habituales

  • overking
  • Tig
  • Fr4nk0