Estoy usando el siguiente código para descargar un archivo de mi servidor y luego escribirlo en el directorio raíz de la tarjeta SD, todo funciona bien:
package com.downloader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import android.os.Environment;
import android.util.Log;
public class Downloader {
    public void DownloadFile(String fileURL, String fileName) {
        try {
            File root = Environment.getExternalStorageDirectory();
            URL u = new URL(fileURL);
            HttpURLConnection c = (HttpURLConnection) u.openConnection();
            c.setRequestMethod("GET");
            c.setDoOutput(true);
            c.connect();
            FileOutputStream f = new FileOutputStream(new File(root, fileName));
            InputStream in = c.getInputStream();
            byte[] buffer = new byte[1024];
            int len1 = 0;
            while ((len1 = in.read(buffer)) > 0) {
                f.write(buffer, 0, len1);
            }
            f.close();
        } catch (Exception e) {
            Log.d("Downloader", e.getMessage());
        }
    }
}
Sin embargo, usar Environment.getExternalStorageDirectory();significa que el archivo siempre se escribirá en la raíz /mnt/sdcard. ¿Es posible especificar una carpeta determinada para escribir el archivo?
Por ejemplo: /mnt/sdcard/myapp/downloads

Respuestas:
File sdCard = Environment.getExternalStorageDirectory(); File dir = new File (sdCard.getAbsolutePath() + "/dir1/dir2"); dir.mkdirs(); File file = new File(dir, "filename"); FileOutputStream f = new FileOutputStream(file); ...fuente
getExternalStorageDirectory()quedó obsoleto en API 29.Agregar permiso al manifiesto de Android
Agregue este permiso WRITE_EXTERNAL_STORAGE a su manifiesto de aplicaciones.
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="your.company.package" android:versionCode="1" android:versionName="0.1"> <application android:icon="@drawable/icon" android:label="@string/app_name"> <!-- ... --> </application> <uses-sdk android:minSdkVersion="7" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> </manifest>Verifique la disponibilidad de almacenamiento externo
Siempre debe verificar primero la disponibilidad. Un fragmento de la documentación oficial de Android sobre almacenamiento externo .
boolean mExternalStorageAvailable = false; boolean mExternalStorageWriteable = false; String state = Environment.getExternalStorageState(); if (Environment.MEDIA_MOUNTED.equals(state)) { // We can read and write the media mExternalStorageAvailable = mExternalStorageWriteable = true; } else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) { // We can only read the media mExternalStorageAvailable = true; mExternalStorageWriteable = false; } else { // Something else is wrong. It may be one of many other states, but all we need // to know is we can neither read nor write mExternalStorageAvailable = mExternalStorageWriteable = false; }Utilice un redactor de archivos
Por último, pero no menos importante, olvídate de
FileOutputStreamy usa aFileWriteren su lugar. Más información sobre esa clase forma el javadoc FileWriter . Es posible que desee agregar más control de errores aquí para informar al usuario.// get external storage file reference FileWriter writer = new FileWriter(getExternalStorageDirectory()); // Writes the content to the file writer.write("This\n is\n an\n example\n"); writer.flush(); writer.close();fuente
FileOutputStream(bueno, no cubre las alternativas). ¿Por qué es mejor usar elFileWriteren su lugar? ¿Es más rápido / más confiable / algo más?FileWritertiene métodos convenientes para escribir cadenas directamente, que no están presentes en unFileOutputStream. Si no está escribiendo archivos de texto,FileWriterno es de mucha ayuda. De hecho, si está escribiendo un archivo de imagen , en realidad no se puede hacer con unFileWriterPor supuesto, si realmente desea una buena API para texto, envuelva suFileOutputStreamenPrintStreamy tendrá los mismos métodos queSystem.out.Encontré la respuesta aquí: http://mytechead.wordpress.com/2014/01/30/android-create-a-file-and-write-to-external-storage/
Dice,
/** * Method to check if user has permissions to write on external storage or not */ public static boolean canWriteOnExternalStorage() { // get the state of your external storage String state = Environment.getExternalStorageState(); if (Environment.MEDIA_MOUNTED.equals(state)) { // if storage is mounted return true Log.v("sTag", "Yes, can write to external storage."); return true; } return false; }y luego usemos este código para escribir en el almacenamiento externo:
// get the path to sdcard File sdcard = Environment.getExternalStorageDirectory(); // to this path add a new directory path File dir = new File(sdcard.getAbsolutePath() + "/your-dir-name/"); // create this directory if not already created dir.mkdir(); // create the file in which we will write the contents File file = new File(dir, "My-File-Name.txt"); FileOutputStream os = outStream = new FileOutputStream(file); String data = "This is the content of my file"; os.write(data.getBytes()); os.close();Y esto es todo. Si ahora visita su carpeta / sdcard / your-dir-name /, verá un archivo llamado - My-File-Name.txt con el contenido especificado en el código.
PD: - Necesita el siguiente permiso -
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />fuente
/sdcard/no siempre es la sdcard.Para descargar un archivo para descargar o carpeta de música en la tarjeta SD
File downlodDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);// or DIRECTORY_PICTURESY no olvide agregar estos permisos en el manifiesto
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />fuente