¿Cómo mover / cambiar el nombre del archivo del almacenamiento interno de la aplicación al almacenamiento externo en Android?

Estoy descargando archivos de Internet y guardando los datos de transmisión en un archivo temporal en el almacenamiento interno de mi aplicación proporcionado por getFilesDir () .

Una vez que se completa la descarga, necesito mover el archivo temporal a mi directorio de descarga en la memoria externa (generalmente una tarjeta SD). Por alguna razón, File.renameTo () no funciona para esto. Supongo que hay un problema porque son dos sistemas de archivos separados, pero aún puedo descargarlo directamente a la tarjeta SD y los URI de los archivos son correctos.

¿Hay alguna otra manera simple y rápida de transferir ese archivo de la memoria interna a externa o tengo que hacer una copia de la stream de bytes y eliminar el original?

Para copiar archivos de la memoria interna a la tarjeta SD y viceversa usando la siguiente pieza de código:

public static void copyFile(File src, File dst) throws IOException { FileChannel inChannel = new FileInputStream(src).getChannel(); FileChannel outChannel = new FileOutputStream(dst).getChannel(); try { inChannel.transferTo(0, inChannel.size(), outChannel); } finally { if (inChannel != null) inChannel.close(); if (outChannel != null) outChannel.close(); } } 

Y funciona…

La memoria interna y externa son dos sistemas de archivos diferentes. Por lo tanto, renameTo () falla.

Deberá copiar el archivo y eliminar el original

Después de copiar el archivo (como muestra la gran respuesta de @barmaley ), no olvide exponerlo en la galería del dispositivo, para que el usuario pueda verlo más tarde.

La razón por la cual tiene que hacerse manualmente es que

Android ejecuta una exploración de medios completa solo al reiniciar y al (re) montar la tarjeta SD

(como muestra esta guía ).

La forma más sencilla de hacerlo es enviando una transmisión para que se invoque el escaneo:

 Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); intent.setData(Uri.fromFile(outputFile)); context.sendBroadcast(intent); 

¡Y voilá! Ahora puede ver su archivo en la galería del dispositivo.

Una alternativa a la copia usando su propia función es usar la clase de la biblioteca de Apache “FileUtils”, en la función llamada copyFile :

 FileUtils.copyFile(src, dst, true); 

Para el archivo Move, la mejor manera es Renombrar su ruta con diferentes rutas y ejemplos de nombre:

 File from = new File(Environment.getExternalStorage().getAbsolutePath()+"/kaic1/imagem.jpg"); File to = new File(Environment.getExternalStorage().getAbsolutePath()+"/kaic2/imagem.jpg"); from.renameTo(to); 

Imagen que:

  • Esta es la ruta interna: pathInternal
  • Y esta es una ruta externa: pathExternal

Pruebe con este código:

 public void moveIn (String pathInternal, String pathExternal) { File fInternal = new File (pathInternal); File fExternal = new File (pathExternal); if (fInternal.exists()) { fInternal.renameTo(fExternal); } } 

Hizo algunas modificaciones triviales en el código de @ barmaley

 public boolean copyFile(File src, File dst) { boolean returnValue = true; FileChannel inChannel = null, outChannel = null; try { inChannel = new FileInputStream(src).getChannel(); outChannel = new FileOutputStream(dst).getChannel(); } catch (FileNotFoundException fnfe) { Log.d(logtag, "inChannel/outChannel FileNotFoundException"); fnfe.printStackTrace(); return false; } try { inChannel.transferTo(0, inChannel.size(), outChannel); } catch (IllegalArgumentException iae) { Log.d(logtag, "TransferTo IllegalArgumentException"); iae.printStackTrace(); returnValue = false; } catch (NonReadableChannelException nrce) { Log.d(logtag, "TransferTo NonReadableChannelException"); nrce.printStackTrace(); returnValue = false; } catch (NonWritableChannelException nwce) { Log.d(logtag, "TransferTo NonWritableChannelException"); nwce.printStackTrace(); returnValue = false; } catch (ClosedByInterruptException cie) { Log.d(logtag, "TransferTo ClosedByInterruptException"); cie.printStackTrace(); returnValue = false; } catch (AsynchronousCloseException ace) { Log.d(logtag, "TransferTo AsynchronousCloseException"); ace.printStackTrace(); returnValue = false; } catch (ClosedChannelException cce) { Log.d(logtag, "TransferTo ClosedChannelException"); cce.printStackTrace(); returnValue = false; } catch (IOException ioe) { Log.d(logtag, "TransferTo IOException"); ioe.printStackTrace(); returnValue = false; } finally { if (inChannel != null) try { inChannel.close(); } catch (IOException e) { e.printStackTrace(); } if (outChannel != null) try { outChannel.close(); } catch (IOException e) { e.printStackTrace(); } } return returnValue; } 

Puedes hacerlo usando operaciones con byte []

define en tu clase:

  public static final String DATA_PATH = Environment.getExternalStorageDirectory().toString() + "/MyAppName/"; 

entonces:

 AssetManager assetManager = context.getAssets(); InputStream in = assetManager.open("data/file.txt"); OutputStream out = new FileOutputStream(DATA_PATH + "data/file.txt"); // Transfer bytes from in to out byte[] buf = new byte[1024]; int len; while ((len = in.read(buf)) > 0) { out.write(buf, 0, len); } in.close(); out.close();