web-dev-qa-db-fra.com

Impossible de créer un dossier sur un stockage externe sur Android

Mon téléphone de développement est un Nexus 5, exécutant Android 4.4.2.

Dans mon application, j'essaie de créer un dossier sur un stockage externe qui stockera les informations de débogage pour mon application. Fondamentalement, il contiendra toutes les commandes exécutées par l'application, de sorte que lorsqu'un utilisateur rencontre un problème, j'ai la possibilité de lui envoyer les informations du dossier de débogage à analyser. 

J'ai commencé par essayer d'écrire un fichier dans le dossier, mais j'ai constaté une erreur lors de la création du dossier. Au début, j'utilisais mkdir(), puis je suis passé à mkdirs(), qui ne fonctionnait pas non plus. 

J'ai <uses-permission Android:name="Android.permission.WRITE_EXTERNAL_STORAGE" /> dans mon manifeste. 

Voici le code pour créer le dossier:

    File folder = new File(Environment.getExternalStorageDirectory() + "/DebugData");

    String path = folder.getPath();

    if(!folder.mkdirs() || !folder.exists()){        
            Log.e(LOG_TAG, path + " failed");
        } else {
            Log.d(LOG_TAG, path + " succeeded");
        } 

Voici ce que j'ai aussi essayé:

    //Check SD card state
    String state = Environment.getExternalStorageState();
    if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state) || !Environment.MEDIA_MOUNTED.equals(state)) {
        Log.e(LOG_TAG, "Error: external storage is read only or unavailable");
    } else {
        Log.d(LOG_TAG, "External storage is not read only or unavailable");
    }

Cela retourne que le stockage externe est pas en lecture seule ou indisponible.

J'ai également essayé différents chemins, tels que File folder = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "Folder1");

Ceci est où il est devenu vraiment déroutant.

J'ai essayé le développement sur différents téléphones. Premièrement, j'ai attrapé un Galaxy S4 GT-i9505 sous Android 4.2.2 et cela a fonctionné. J'ai pu créer les dossiers et leur écrire. Cela m'a montré que le code fonctionnait. De plus, le chemin renvoyé en exécutant le code sur le S4 et le Nexus 5 était identique. 

Ensuite, j'ai pensé qu'il pourrait s'agir d'une version spécifique d'Android. J'ai donc attrapé un Nexus 4 avec Android 4.4.2 et le code a également fonctionné. Créé les dossiers et m'a permis de leur écrire. 

Aucun des téléphones ne sont enracinés et sont tous en stock standard. Il n’existe pas d’applications spéciales ni d’autres réglages du Nexus 5 susceptibles de poser des problèmes d’autorisations. La connexion est définie sur Périphérique multimédia (MTP). 

MODIFIER:

Je devrais ajouter que j'ai essayé le suivi qui n'a pas non plus fonctionné:

  • Écrire un fichier dans le répertoire racine du stockage externe
  • Création du fichier dans le répertoire racine du stockage externe et écriture dans celui-ci
  • Créer un dossier dans un chemin indiqué et y écrire un fichier
  • Créer le fichier dans le chemin indiqué et y écrire

Je suis confus quant à la cause de ce problème. Y at-il autre chose que je puisse tester ou modifier pour résoudre le problème? 

EDIT 2:

Il se trouve que le problème était dû, je pense, à l'indexation.

Fondamentalement, tous les autres périphériques sur lesquels j'ai testé, m'ont permis de reconnecter la connexion USB et d'afficher les fichiers et les dossiers créés.

Pour une raison quelconque, mon Nexus 5 n'indexe pas les dossiers/fichiers, même s'ils existent.

J'ai téléchargé une autre application tierce de l'explorateur de fichiers et constaté que tous les dossiers et fichiers étaient présents.

Donc, pour afficher ces dossiers et fichiers via le débogage USB, je dois redémarrer le téléphone pour les réindexer, ce qui semble assez gênant, mais il vaut mieux que cela ne fonctionne pas du tout.

Merci. 

14
benallansmith

En tant que problème d’indexation avec le Nexus, cela a fonctionné pour moi:

MediaScannerConnection.scanFile(this, new String[] { file.toString() }, null,
        new MediaScannerConnection.OnScanCompletedListener() {
            public void onScanCompleted(String path, Uri uri) {
                Log.i("ExternalStorage", "Scanned " + path + ":");
                Log.i("ExternalStorage", "-> uri=" + uri);
            }
});

Vous devriez l'appeler tout de suite après avoir créé et sauvegardé le fichier. En utilisant le scanner, j'ai pu voir les fichiers et les répertoires nouvellement créés simplement en rebranchant le périphérique.

Selon les docs :

MediaScannerConnection permet aux applications de transmettre un nouveau fichier fichier multimédia créé ou téléchargé sur le service d'analyse de média. Le Le service d'analyse des médias lira les métadonnées à partir du fichier et ajoutera le fichier au fournisseur de contenu multimédia.

J'espère que ceci aide quelqu'un d'autre.

7

Il se trouve que le problème était dû, je pense, à l'indexation. 

Fondamentalement, tous les autres périphériques sur lesquels j'ai testé, m'ont permis de reconnecter la connexion USB et d'afficher les fichiers et les dossiers créés.

Pour une raison quelconque, mon Nexus 5 n'indexe pas les dossiers/fichiers, même s'ils existent.

J'ai téléchargé une autre application tierce de l'explorateur de fichiers et constaté que tous les dossiers et fichiers étaient présents. 

Donc, pour afficher ces dossiers et fichiers via le débogage USB, je dois redémarrer le téléphone pour les réindexer, ce qui semble assez gênant, mais il vaut mieux que cela ne fonctionne pas du tout. 

4
benallansmith

Avait le même problème. En fait, je testais sur Android 6 et je n'ai pas vérifié l'autorisation d'exécution WRITE_EXTERNAL_STORAGE.

3
stoefln

Tout d'abord, new File() est juste créer un objet pour le fichier de connexion.
vous voulez utiliser ce fichier, le fichier est existant ou createNewFile().
Si vous souhaitez utiliser ce fichier pour créer un répertoire, vérifiez que le fichier existe, isDirectory() après mkDir().
Deuxièmement, vérifiez que Environment.getExternalStorageDirectory est un chemin variable.
Vous pouvez utiliser DDMS ou ADB pour le travail.
De plus, je pense que vous ajoutez l’autorisation de lire le stockage externe en cas d’erreur.

2
Amadas

Pour Android sdk version 23 et ultérieure, vous devez vérifier si l'utilisateur a accordé l'autorisation de stockage externe.

private void createFolder() {
    if (isStoragePermissionGranted()) {
        File folder = new File(Environment.getExternalStorageDirectory()+ File.separator + "DebugData");

        if(!folder.exists()){
            folder.mkdir();
        }
    }

public  boolean isStoragePermissionGranted() {
    if (Build.VERSION.SDK_INT >= 23) {
        if (checkSelfPermission(Android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
                == PackageManager.PERMISSION_GRANTED) {
            return true;
        } else {
            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
            return false;
        }
    }
    else { //permission is automatically granted on sdk<23 upon installation
        return true;
    }
}

Le code ci-dessus a fonctionné pour moi et j'espère que cela fonctionnera pour vous.

1
Bookan

Si vous utilisez un appareil Android avec api> = 23, vous devez demander l'autorisation de l'utilisateur avant d'appeler la fonction mkdir (). On peut trouver ma réponse précédente avec un exemple de code https://stackoverflow.com/a/38694026/5089713

1
Diiiiii

En général, je fais ceci:

/**
 * Return a dedicated directory named "MyApp" at the top of external storage
 */
public static file getDataDir() {
    File sdcard = Environment.getExternalStorageDirectory();
    if( sdcard == null || !sdcard.isDirectory() ) {
        // TODO: warning popup
        Log.w(TAG, "Storage card not found " + sdcard);
        return null;
    }
    File dataDir = new File(sdcard, "MyApp");
    if( !confirmDir(dataDir) ) {
        // TODO: warning popup
        Log.e(TAG, "Unable to create " + dataDir);
        return null;
    }
    return dataDir;
}   

private static boolean confirmDir(File dir) {
    if (dir.isDirectory()) return true;  // already exists
    if (dir.exists()) return false;      // already exists, but is not a directory
    return dir.mkdirs();                 // create it
}       

Ajoutez également cette permission à votre manifeste:

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

Si vous souhaitez un stockage privé (généralement sous/data /) pour votre application (pas sur sdcard), cherchez alors getDir(), getFilesDir(), fileList(), openFileInput(), openFileOutput(), etc.

Il existe également des fonctions d'assistance pour obtenir des répertoires privés dans la carte SD pour API 8 et versions ultérieures: getExternalFilesDir(), getExternalCacheDir(), etc.

0
Edward Falk