Como criar diretório automaticamente no cartão SD

189

Estou tentando salvar meu arquivo no seguinte local,
FileOutputStream fos = new FileOutputStream("/sdcard/Wallpaper/"+fileName); mas estou recebendo a exceção java.io.FileNotFoundException
No entanto, quando coloco o caminho como "/sdcard/"ele funciona.

Agora, estou assumindo que não sou capaz de criar um diretório automaticamente dessa maneira.

Alguém pode sugerir como criar um directory and sub-directorycódigo usando?

Kshitij Aggarwal
fonte

Respostas:

449

Se você criar um objeto File que agrupe o diretório de nível superior, poderá chamar seu método mkdirs () para criar todos os diretórios necessários. Algo como:

// create a File object for the parent directory
File wallpaperDirectory = new File("/sdcard/Wallpaper/");
// have the object build the directory structure, if needed.
wallpaperDirectory.mkdirs();
// create a File object for the output file
File outputFile = new File(wallpaperDirectory, filename);
// now attach the OutputStream to the file object, instead of a String representation
FileOutputStream fos = new FileOutputStream(outputFile);

Nota: Pode ser aconselhável usar Environment.getExternalStorageDirectory () para obter o diretório "Cartão SD", pois isso pode mudar se um telefone aparecer com algo diferente de um cartão SD (como flash embutido, a Iphone). De qualquer forma, lembre-se de que você precisa verificar se ele está realmente lá, pois o cartão SD pode ser removido.

ATUALIZAÇÃO: desde o nível 4 da API (1.6), você também precisará solicitar a permissão. Algo assim (no manifesto) deve funcionar:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Jeremy Logan
fonte
1
sim, os comprimidos Samsung subsequentemente libertados usar flash embutido
CQM
2
não esqueça de adicionar ao AndroidManifest.xml o direito de gravar stackoverflow.com/a/4435708/579646
max4ever
1
Parece que isso não está funcionando se eu tiver uma subpasta, como /sdcard/com.my.code/data? Como eu poderia resolver isso?
Lony
Além de criar esse diretório também? Existe um comando como 'force' no unix mkdir?
Lony
4
Não funciona no KitKat, sdcard físico externo.
Celoftis
57

Teve o mesmo problema e apenas deseja adicionar que AndroidManifest.xml também precisa desta permissão:

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

Aqui está o que funciona para mim.

 uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" 

no seu manifesto e no código abaixo

public static boolean createDirIfNotExists(String path) {
    boolean ret = true;

    File file = new File(Environment.getExternalStorageDirectory(), path);
    if (!file.exists()) {
        if (!file.mkdirs()) {
            Log.e("TravellerLog :: ", "Problem creating Image folder");
            ret = false;
        }
    }
    return ret;
}
Vijay Kumar AB
fonte
path é o nome da pasta que você deseja criar. Se você enviou um caminho como o MusicDownload .. Torna-se automaticamente / sdcard / MusicDownload. Shajeel Afzal
shehzy
Ela lança java.io.IOException exceção: Falha na abertura: ENOENT (Nenhum tal lima ou diretório)
Anand Savjani
24

Na verdade, usei parte do @fiXedd asnwer e funcionou para mim:

  //Create Folder
  File folder = new File(Environment.getExternalStorageDirectory().toString()+"/Aqeel/Images");
  folder.mkdirs();

  //Save the path as a string value
  String extStorageDirectory = folder.toString();

  //Create New file and name it Image2.PNG
  File file = new File(extStorageDirectory, "Image2.PNG");

Verifique se você está usando mkdirs () e não mkdir () para criar o caminho completo

Amt87
fonte
Como é essa "parte" da resposta do @fixedd? Sua resposta foi usar File.mkdirs(). Ele então mostrou um exemplo de uso.
Doomsknight
Na verdade, eu não me lembro qual era a diferença, mas eu acho que houve algumas edições ... By the way eu mencionei que eu usei a resposta para obter a solução
Amt87
12

Com a API 8 e superior, a localização do cartão SD mudou. A resposta do @ fiXedd é boa, mas para um código mais seguro, você deve Environment.getExternalStorageState()verificar se a mídia está disponível. Em seguida, você pode usar getExternalFilesDir()para navegar para o diretório desejado (supondo que você esteja usando a API 8 ou superior).

Você pode ler mais na documentação do SDK .

Nick Ruiz
fonte
8

Verifique se o armazenamento externo está presente: http://developer.android.com/guide/topics/data/data-storage.html#filesExternal

private boolean isExternalStoragePresent() {

        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;
        }
        if (!((mExternalStorageAvailable) && (mExternalStorageWriteable))) {
            Toast.makeText(context, "SD card not present", Toast.LENGTH_LONG)
                    .show();

        }
        return (mExternalStorageAvailable) && (mExternalStorageWriteable);
    }
Parth mehta
fonte
6

Não se esqueça de verificar se você não possui caracteres especiais nos nomes dos arquivos / pastas. Aconteceu comigo com ":" quando eu estava definindo nomes de pastas usando variáveis

caracteres não permitidos nos nomes de arquivos / pastas

"* /: <>? \ |

Você pode achar esse código útil nesse caso.

O código abaixo remove todos os ":" e os substitui por "-"

//actualFileName = "qwerty:asdfg:zxcvb" say...

    String[] tempFileNames;
    String tempFileName ="";
    String delimiter = ":";
    tempFileNames = actualFileName.split(delimiter);
    tempFileName = tempFileNames[0];
    for (int j = 1; j < tempFileNames.length; j++){
        tempFileName = tempFileName+" - "+tempFileNames[j];
    }
    File file = new File(Environment.getExternalStorageDirectory(), "/MyApp/"+ tempFileName+ "/");
    if (!file.exists()) {
        if (!file.mkdirs()) {
        Log.e("TravellerLog :: ", "Problem creating Image folder");
        }
    }
Praveen
fonte
+1 ya eu também tentei com: e obtive um erro e finalmente encontrei esse problema e removi: e todos os outros caracteres especiais.
precisa
6

Eu enfrentei o mesmo problema. Existem dois tipos de permissões no Android:

  • Perigoso (acesso a contatos, gravação no armazenamento externo ...)
  • Normal (permissões normais são aprovadas automaticamente pelo Android, enquanto permissões perigosas precisam ser aprovadas por usuários do Android.)

Aqui está a estratégia para obter permissões perigosas no Android 6.0

  • Verifique se você tem a permissão concedida
  • Se seu aplicativo já tiver a permissão, vá em frente e execute normalmente.
  • Se o seu aplicativo ainda não tiver a permissão, peça ao usuário que aprove
  • Ouça a aprovação do usuário em onRequestPermissionsResult

Aqui está o meu caso: preciso gravar no armazenamento externo.

Primeiro, verifico se tenho a permissão:

...
private static final int REQUEST_WRITE_STORAGE = 112;
...
boolean hasPermission = (ContextCompat.checkSelfPermission(activity,
            Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED);
if (!hasPermission) {
    ActivityCompat.requestPermissions(parentActivity,
                new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
                REQUEST_WRITE_STORAGE);
}

Em seguida, verifique a aprovação do usuário:

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    switch (requestCode)
    {
        case REQUEST_WRITE_STORAGE: {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
            {
                //reload my activity with permission granted or use the features what required the permission
            } else
            {
                Toast.makeText(parentActivity, "The app was not allowed to write to your storage. Hence, it cannot function properly. Please consider granting it this permission", Toast.LENGTH_LONG).show();
            }
        }
    }    
}
Syed Abdul Basit
fonte
5

Eu estava enfrentando o mesmo problema, incapaz de criar um diretório no Galaxy S, mas consegui criá-lo com sucesso no Nexus e no Samsung Droid. Como eu o consertei adicionando a seguinte linha de código:

File dir = new File(Environment.getExternalStorageDirectory().getPath()+"/"+getPackageName()+"/");
dir.mkdirs();
Garima Srivastava
fonte
5
File sdcard = Environment.getExternalStorageDirectory();
File f=new File(sdcard+"/dor");
f.mkdir();

isso criará uma pasta chamada dor no seu sdcard. em seguida, para buscar o arquivo para eg- filename.json, que é inserido manualmente na pasta dor . Gostar:

 File file1 = new File(sdcard,"/dor/fitness.json");
 .......
 .....

<permissão de uso android: name = "android.permission.WRITE_EXTERNAL_STORAGE" />

e não se esqueça de adicionar código no manifesto

Jayant Singh
fonte
4
     //Create File object for Parent Directory
File wallpaperDir = new File(Environment.getExternalStorageDirectory().getAbsoluteFile() +File.separator + "wallpaper");
if (!wallpaperDir.exists()) {
wallpaperDir.mkdir();
}


File out = new File(wallpaperDir, wallpaperfile);
FileOutputStream outputStream = new FileOutputStream(out);
vikseln
fonte
3

Acabando de publicar a publicação de Vijay ...


Manifesto

uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"

Função

public static boolean createDirIfNotExists(String path) {
    boolean ret = true;

    File file = new File(Environment.getExternalStorageDirectory(), path);
    if (!file.exists()) {
        if (!file.mkdirs()) {
            Log.e("TravellerLog :: ", "Problem creating Image folder");
            ret = false;
        }
    }
    return ret;
}

Uso

createDirIfNotExists("mydir/"); //Create a directory sdcard/mydir
createDirIfNotExists("mydir/myfile") //Create a directory and a file in sdcard/mydir/myfile.txt

Você pode verificar se há erros

if(createDirIfNotExists("mydir/")){
     //Directory Created Success
}
else{
    //Error
}
Ismael Di Vita
fonte
3

Isso criará uma pasta no sdcard com o nome da pasta que você fornecer.

File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/Folder name");
        if (!file.exists()) {
            file.mkdirs();
        }
Shweta Chauhan
fonte
1

Você pode usar / sdcard / em vez de Environment.getExternalStorageDirectory ()

private static String DB_PATH = "/sdcard/Android/data/com.myawesomeapp.app/";

File dbdir = new File(DB_PATH);
dbdir.mkdirs();
Peter Drinnan
fonte
4
Não, você não deve usar um caminho codificado em vez de chamar a API adequada. Fazer isso introduz uma dependência imprudente dos detalhes de uma implementação específica.
Chris Stratton
1
ivmage.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            Intent i = new Intent(
                    Intent.ACTION_PICK,
                    android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);

            startActivityForResult(i, RESULT_LOAD_IMAGE_ADD);

        }
    });`
Vishnu Namboodiri
fonte