Trouver un emplacement de carte SD externe

Existe-t-il un moyen universel de trouver l'emplacement d'une carte SD externe?

S'il vous plaît, ne pas confondre avec Stockage Externe . Environment.getExternalStorageState() renvoie le chemin vers le point de montage SD interne comme "/mnt / sdcard". Mais la question concerne le développement durable externe. Comment obtenir un chemin comme "/mnt/sdcard/external_sd" (il peut varier d'un appareil à l'autre)?

je pense que je vais finir avec le filtrage de la commande mount par nom de système de fichiers. Mais je ne suis pas sûr que cette façon soit assez robuste.

182
demandé sur Lightness Races in Orbit 2011-04-17 20:57:49

20 réponses

Environment.getExternalStorageState() renvoie le chemin d'accès à la SD interne de point de montage comme "/mnt/sdcard"

Non, Environment.getExternalStorageDirectory() renvoie à ce que le fabricant du dispositif considère comme un "stockage externe". Sur certains appareils, il s'agit de supports amovibles, comme une carte SD. Sur certains appareils, c'est une partie de l'appareil flash. Ici, " stockage externe "signifie" le matériel accessible via le mode de stockage de masse USB lorsqu'il est monté sur une machine hôte", au moins pour Android 1.x et 2.x.

mais la question Est sur le SD externe. Comment obtenir un chemin comme "/mnt/sdcard/external_sd" (il peut varier d'un appareil à l'autre)?

Android n'a pas de concept de "SD externe", mis à part le stockage externe, comme décrit ci-dessus.

si un fabricant d'appareil a choisi d'avoir un stockage externe être flash à bord et a également une carte SD, vous aurez besoin de contacter ce fabricant pour déterminer si oui ou non vous pouvez utiliser la carte SD (non garanti) et quelles sont les règles pour l'utiliser, comme quel chemin à utiliser pour elle.


mise à jour

deux choses récentes à noter:

tout d'abord, sur Android 4.4+, vous n'avez pas accès en écriture à des supports amovibles (par exemple, "SD externe"), sauf pour les emplacements sur ce média qui pourraient être retournés par getExternalFilesDirs() et getExternalCacheDirs() . Voir L'excellente analyse de Dave Smith de ceci, particulièrement si vous voulez les détails de bas niveau.

deuxièmement, de peur que quelqu'un ne se demande si l'accès aux médias amovibles fait ou non partie du SDK Android, voici évaluation de Dianne Hackborn :

...gardez à l'esprit: Jusqu'à Android 4.4, la plate-forme officielle Android n'a pas pris en charge les cartes SD à tous sauf pour deux cas particuliers: la disposition de stockage ancienne école où le stockage externe est une carte SD (qui est encore prise en charge par la plate-forme aujourd'hui), et une petite fonctionnalité ajoutée à Android 3.0 où il numériserait les cartes SD supplémentaires et les ajouter au fournisseur de médias et de donner aux applications l'accès en lecture seule à leurs fichiers (qui est également encore prise en charge dans la plate-forme aujourd'hui).

Android 4.4 est la première version de la plate-forme qui a effectivement permis aux applications d'utiliser des cartes SD pour stockage. Tout accès à eux avant cela était par le biais D'API privées et sans support. Nous avons maintenant une API assez riche dans la plate-forme qui permet aux applications d'utiliser les cartes SD d'une manière supportée, de meilleures façons qu'elles n'ont pu le faire auparavant: elles peuvent utiliser gratuitement leur zone de stockage spécifique à l'application sans avoir besoin de permissions dans l'application, et peuvent accéder à tous les autres fichiers sur la carte SD aussi longtemps qu'elles passent par le gestionnaire de fichiers, encore une fois sans avoir besoin de permissions spéciales.

147
répondu CommonsWare 2014-04-11 13:03:57

j'ai trouvé la solution suivante basée sur quelques réponses trouvées ici.

CODE:

public class ExternalStorage {

    public static final String SD_CARD = "sdCard";
    public static final String EXTERNAL_SD_CARD = "externalSdCard";

    /**
     * @return True if the external storage is available. False otherwise.
     */
    public static boolean isAvailable() {
        String state = Environment.getExternalStorageState();
        if (Environment.MEDIA_MOUNTED.equals(state) || Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
            return true;
        }
        return false;
    }

    public static String getSdCardPath() {
        return Environment.getExternalStorageDirectory().getPath() + "/";
    }

    /**
     * @return True if the external storage is writable. False otherwise.
     */
    public static boolean isWritable() {
        String state = Environment.getExternalStorageState();
        if (Environment.MEDIA_MOUNTED.equals(state)) {
            return true;
        }
        return false;

    }

    /**
     * @return A map of all storage locations available
     */
    public static Map<String, File> getAllStorageLocations() {
        Map<String, File> map = new HashMap<String, File>(10);

        List<String> mMounts = new ArrayList<String>(10);
        List<String> mVold = new ArrayList<String>(10);
        mMounts.add("/mnt/sdcard");
        mVold.add("/mnt/sdcard");

        try {
            File mountFile = new File("/proc/mounts");
            if(mountFile.exists()){
                Scanner scanner = new Scanner(mountFile);
                while (scanner.hasNext()) {
                    String line = scanner.nextLine();
                    if (line.startsWith("/dev/block/vold/")) {
                        String[] lineElements = line.split(" ");
                        String element = lineElements[1];

                        // don't add the default mount path
                        // it's already in the list.
                        if (!element.equals("/mnt/sdcard"))
                            mMounts.add(element);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        try {
            File voldFile = new File("/system/etc/vold.fstab");
            if(voldFile.exists()){
                Scanner scanner = new Scanner(voldFile);
                while (scanner.hasNext()) {
                    String line = scanner.nextLine();
                    if (line.startsWith("dev_mount")) {
                        String[] lineElements = line.split(" ");
                        String element = lineElements[2];

                        if (element.contains(":"))
                            element = element.substring(0, element.indexOf(":"));
                        if (!element.equals("/mnt/sdcard"))
                            mVold.add(element);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }


        for (int i = 0; i < mMounts.size(); i++) {
            String mount = mMounts.get(i);
            if (!mVold.contains(mount))
                mMounts.remove(i--);
        }
        mVold.clear();

        List<String> mountHash = new ArrayList<String>(10);

        for(String mount : mMounts){
            File root = new File(mount);
            if (root.exists() && root.isDirectory() && root.canWrite()) {
                File[] list = root.listFiles();
                String hash = "[";
                if(list!=null){
                    for(File f : list){
                        hash += f.getName().hashCode()+":"+f.length()+", ";
                    }
                }
                hash += "]";
                if(!mountHash.contains(hash)){
                    String key = SD_CARD + "_" + map.size();
                    if (map.size() == 0) {
                        key = SD_CARD;
                    } else if (map.size() == 1) {
                        key = EXTERNAL_SD_CARD;
                    }
                    mountHash.add(hash);
                    map.put(key, root);
                }
            }
        }

        mMounts.clear();

        if(map.isEmpty()){
                 map.put(SD_CARD, Environment.getExternalStorageDirectory());
        }
        return map;
    }
}

UTILISATION:

Map<String, File> externalLocations = ExternalStorage.getAllStorageLocations();
File sdCard = externalLocations.get(ExternalStorage.SD_CARD);
File externalSdCard = externalLocations.get(ExternalStorage.EXTERNAL_SD_CARD);
60
répondu Richard 2015-05-10 02:41:40

j'avais une application qui utilisait un ListPreference où l'utilisateur devait choisir l'endroit où il voulait enregistrer quelque chose. Dans cette application, j'ai scanné /proc/mounts et /system/etc/vold.fstab pour points de montage sdcard. J'ai stocké les points de montage de chaque fichier dans deux ArrayList distincts.

Ensuite, j'ai comparé une liste avec les autres et jeté des éléments qui n'étaient pas dans les deux listes. Cela m'a donné une liste des chemins racine pour chaque carte SD.

de là, j'ai testé les chemins avec File.exists() , File.isDirectory() , et File.canWrite() . Si l'un de ces tests était faux, j'ai écarté ce chemin de la liste.

peu importe ce qui restait dans la liste, j'ai converti en tableau String[] pour qu'il puisse être utilisé par l'attribut ListPreference valeurs.

vous pouvez voir le code ici: http://sapienmobile.com/?p=204

36
répondu Baron 2014-04-15 02:02:52

afin de récupérer tous les stockages externes (s'ils sont cartes SD ou stockages internes non amovibles ), vous pouvez utiliser le code suivant:

final String state = Environment.getExternalStorageState();

if ( Environment.MEDIA_MOUNTED.equals(state) || Environment.MEDIA_MOUNTED_READ_ONLY.equals(state) ) {  // we can read the External Storage...           
    //Retrieve the primary External Storage:
    final File primaryExternalStorage = Environment.getExternalStorageDirectory();

    //Retrieve the External Storages root directory:
    final String externalStorageRootDir;
    if ( (externalStorageRootDir = primaryExternalStorage.getParent()) == null ) {  // no parent...
        Log.d(TAG, "External Storage: " + primaryExternalStorage + "\n");
    }
    else {
        final File externalStorageRoot = new File( externalStorageRootDir );
        final File[] files = externalStorageRoot.listFiles();

        for ( final File file : files ) {
            if ( file.isDirectory() && file.canRead() && (file.listFiles().length > 0) ) {  // it is a real directory (not a USB drive)...
                Log.d(TAG, "External Storage: " + file.getAbsolutePath() + "\n");
            }
        }
    }
}

alternativement, vous pouvez utiliser le système .getenv ("EXTERNAL_STORAGE") pour récupérer le répertoire de stockage externe primaire (par exemple "/storage / sdcard0 " ) et le système .getenv ("SECONDARY_STORAGE") pour retirer la liste de tous les répertoires secondaires (par exemple " /storage/extSdCard:/storage/UsbDriveA:/storage/UsbDriveB " ). Rappelez-vous que, dans ce cas également, vous pouvez filtrer la liste des annuaires secondaires afin d'exclure les lecteurs USB.

dans tous les cas, s'il vous plaît noter que l'utilisation de chemins codés hard est toujours une mauvaise approche (expecially when chaque fabricant peut le changer comme il lui plaît).

17
répondu Paolo Rovelli 2013-11-07 14:03:36

vous pouvez essayer d'utiliser la fonction de bibliothèque de soutien appelé de ContextCompat.getExternalFilesDirs() :

      final File[] appsDir=ContextCompat.getExternalFilesDirs(getActivity(),null);
      final ArrayList<File> extRootPaths=new ArrayList<>();
      for(final File file : appsDir)
        extRootPaths.add(file.getParentFile().getParentFile().getParentFile().getParentFile());

le premier est le stockage externe primaire, et les autres sont censés être de véritables chemins SD-cards.

La raison pour laquelle les multiples ".getParentFile () "doit remonter un autre dossier, puisque le chemin original est

.../Android/data/YOUR_APP_PACKAGE_NAME/files/

EDIT: voici un moyen plus complet que j'ai créé, pour obtenir les chemins SD-cards:

  /**
   * returns a list of all available sd cards paths, or null if not found.
   *
   * @param includePrimaryExternalStorage set to true if you wish to also include the path of the primary external storage
   */
  @TargetApi(Build.VERSION_CODES.HONEYCOMB)
  public static List<String> getSdCardPaths(final Context context, final boolean includePrimaryExternalStorage)
    {
    final File[] externalCacheDirs=ContextCompat.getExternalCacheDirs(context);
    if(externalCacheDirs==null||externalCacheDirs.length==0)
      return null;
    if(externalCacheDirs.length==1)
      {
      if(externalCacheDirs[0]==null)
        return null;
      final String storageState=EnvironmentCompat.getStorageState(externalCacheDirs[0]);
      if(!Environment.MEDIA_MOUNTED.equals(storageState))
        return null;
      if(!includePrimaryExternalStorage&&VERSION.SDK_INT>=VERSION_CODES.HONEYCOMB&&Environment.isExternalStorageEmulated())
        return null;
      }
    final List<String> result=new ArrayList<>();
    if(includePrimaryExternalStorage||externalCacheDirs.length==1)
      result.add(getRootOfInnerSdCardFolder(externalCacheDirs[0]));
    for(int i=1;i<externalCacheDirs.length;++i)
      {
      final File file=externalCacheDirs[i];
      if(file==null)
        continue;
      final String storageState=EnvironmentCompat.getStorageState(file);
      if(Environment.MEDIA_MOUNTED.equals(storageState))
        result.add(getRootOfInnerSdCardFolder(externalCacheDirs[i]));
      }
    if(result.isEmpty())
      return null;
    return result;
    }

  /** Given any file/folder inside an sd card, this will return the path of the sd card */
  private static String getRootOfInnerSdCardFolder(File file)
    {
    if(file==null)
      return null;
    final long totalSpace=file.getTotalSpace();
    while(true)
      {
      final File parentFile=file.getParentFile();
      if(parentFile==null||parentFile.getTotalSpace()!=totalSpace)
        return file.getAbsolutePath();
      file=parentFile;
      }
    }
15
répondu android developer 2017-02-15 07:46:43

comme Richard j'utilise aussi /proc / mounts fichier pour obtenir la liste des options de stockage disponibles

public class StorageUtils {

    private static final String TAG = "StorageUtils";

    public static class StorageInfo {

        public final String path;
        public final boolean internal;
        public final boolean readonly;
        public final int display_number;

        StorageInfo(String path, boolean internal, boolean readonly, int display_number) {
            this.path = path;
            this.internal = internal;
            this.readonly = readonly;
            this.display_number = display_number;
        }

        public String getDisplayName() {
            StringBuilder res = new StringBuilder();
            if (internal) {
                res.append("Internal SD card");
            } else if (display_number > 1) {
                res.append("SD card " + display_number);
            } else {
                res.append("SD card");
            }
            if (readonly) {
                res.append(" (Read only)");
            }
            return res.toString();
        }
    }

    public static List<StorageInfo> getStorageList() {

        List<StorageInfo> list = new ArrayList<StorageInfo>();
        String def_path = Environment.getExternalStorageDirectory().getPath();
        boolean def_path_internal = !Environment.isExternalStorageRemovable();
        String def_path_state = Environment.getExternalStorageState();
        boolean def_path_available = def_path_state.equals(Environment.MEDIA_MOUNTED)
                                    || def_path_state.equals(Environment.MEDIA_MOUNTED_READ_ONLY);
        boolean def_path_readonly = Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED_READ_ONLY);
        BufferedReader buf_reader = null;
        try {
            HashSet<String> paths = new HashSet<String>();
            buf_reader = new BufferedReader(new FileReader("/proc/mounts"));
            String line;
            int cur_display_number = 1;
            Log.d(TAG, "/proc/mounts");
            while ((line = buf_reader.readLine()) != null) {
                Log.d(TAG, line);
                if (line.contains("vfat") || line.contains("/mnt")) {
                    StringTokenizer tokens = new StringTokenizer(line, " ");
                    String unused = tokens.nextToken(); //device
                    String mount_point = tokens.nextToken(); //mount point
                    if (paths.contains(mount_point)) {
                        continue;
                    }
                    unused = tokens.nextToken(); //file system
                    List<String> flags = Arrays.asList(tokens.nextToken().split(",")); //flags
                    boolean readonly = flags.contains("ro");

                    if (mount_point.equals(def_path)) {
                        paths.add(def_path);
                        list.add(0, new StorageInfo(def_path, def_path_internal, readonly, -1));
                    } else if (line.contains("/dev/block/vold")) {
                        if (!line.contains("/mnt/secure")
                            && !line.contains("/mnt/asec")
                            && !line.contains("/mnt/obb")
                            && !line.contains("/dev/mapper")
                            && !line.contains("tmpfs")) {
                            paths.add(mount_point);
                            list.add(new StorageInfo(mount_point, false, readonly, cur_display_number++));
                        }
                    }
                }
            }

            if (!paths.contains(def_path) && def_path_available) {
                list.add(0, new StorageInfo(def_path, def_path_internal, def_path_readonly, -1));
            }

        } catch (FileNotFoundException ex) {
            ex.printStackTrace();
        } catch (IOException ex) {
            ex.printStackTrace();
        } finally {
            if (buf_reader != null) {
                try {
                    buf_reader.close();
                } catch (IOException ex) {}
            }
        }
        return list;
    }    
}
12
répondu Vitaliy Polchuk 2013-11-14 16:03:48

il est possible de trouver où des cartes SD supplémentaires sont montées en lisant /proc/mounts (fichier Linux standard) et en contre-vérifiant vold data ( /system/etc/vold.conf ). Et notez que l'emplacement retourné par Environment.getExternalStorageDirectory() peut ne pas apparaître en configuration vold (dans certains appareils c'est un stockage interne qui ne peut pas être démonté), mais doit tout de même être inclus dans la liste. Toutefois, nous n'avons pas trouver un bon moyen de les décrire à l'utilisateur .

10
répondu Jan Hudec 2017-05-23 12:26:27

j'essaie toutes les solutions à l'intérieur de ce thème sur cette fois. Mais tous ne fonctionnaient pas correctement sur les appareils avec une carte externe (amovible) et une carte interne (non amovible). Chemin de la carte externe pas possible obtenir à partir de la commande' mount', à partir du fichier' proc/mounts', etc.

et je crée ma propre solution (sur Paulo Luan's):

String sSDpath = null;
File   fileCur = null;
for( String sPathCur : Arrays.asList( "ext_card", "external_sd", "ext_sd", "external", "extSdCard",  "externalSdCard")) // external sdcard
{
   fileCur = new File( "/mnt/", sPathCur);
   if( fileCur.isDirectory() && fileCur.canWrite())
   {
     sSDpath = fileCur.getAbsolutePath();
     break;
   }
}
fileCur = null;
if( sSDpath == null)  sSDpath = Environment.getExternalStorageDirectory().getAbsolutePath();
7
répondu Tapa Save 2015-08-19 00:55:39

utilisez simplement ceci:

String primary_sd = System.getenv("EXTERNAL_STORAGE");
if(primary_sd != null)
    Log.i("EXTERNAL_STORAGE", primary_sd);
String secondary_sd = System.getenv("SECONDARY_STORAGE");
if(secondary_sd != null)
    Log.i("SECONDARY_STORAGE", secondary_sd)
5
répondu ray pixar 2014-08-08 05:23:48

si vous regardez le code source pour android.os.Environment vous verrez que Android dépend fortement sur les variables d'environnement pour les chemins. Vous pouvez utiliser la variable d'environnement "SECONDARY_STORAGE" pour trouver le chemin vers la carte SD amovible.

/**
 * Get a file using an environmental variable.
 *
 * @param variableName
 *         The Environment variable name.
 * @param paths
 *         Any paths to the file if the Environment variable was not found.
 * @return the File or {@code null} if the File could not be located.
 */
private static File getDirectory(String variableName, String... paths) {
    String path = System.getenv(variableName);
    if (!TextUtils.isEmpty(path)) {
        if (path.contains(":")) {
            for (String _path : path.split(":")) {
                File file = new File(_path);
                if (file.exists()) {
                    return file;
                }
            }
        } else {
            File file = new File(path);
            if (file.exists()) {
                return file;
            }
        }
    }
    if (paths != null && paths.length > 0) {
        for (String _path : paths) {
            File file = new File(_path);
            if (file.exists()) {
                return file;
            }
        }
    }
    return null;
}

exemple d'usage:

public static final File REMOVABLE_STORAGE = getDirectory("SECONDARY_STORAGE");
5
répondu Jared Rummler 2015-08-07 21:59:31

Voici la façon dont j'utilise pour trouver la carte externe. Utilisez le Mont cmd return puis analysez la partie vfat.

String s = "";
try {
Process process = new ProcessBuilder().command("mount")
        .redirectErrorStream(true).start();

process.waitFor();

InputStream is = process.getInputStream();
byte[] buffer = new byte[1024];
while (is.read(buffer) != -1) {
    s = s + new String(buffer);
}
is.close();
} catch (Exception e) {
e.printStackTrace();
}

//用行分隔mount列表
String[] lines = s.split("\n");
for(int i=0; i<lines.length; i++) {
//如果行内有挂载路径且为vfat类型,说明可能是内置或者外置sd的挂载点
if(-1 != lines[i].indexOf(path[0]) && -1 != lines[i].indexOf("vfat")) {
    //再用空格分隔
    String[] blocks = lines[i].split("\s");
    for(int j=0; j<blocks.length; j++) {
        //判断是否是挂载为vfat类型
        if(-1 != blocks[j].indexOf(path[0])) {
            //Test if it is the external sd card.
        }
    }
}
}
4
répondu Fakebear 2012-02-23 02:25:14

Existe-t-il un moyen universel de trouver l'emplacement d'une carte SD externe?

Par de façon universelle , si vous voulez dire de manière officielle; oui il y en a un.

dans le niveau 19 de L'API, c'est-à-dire dans la version 4.4 Kitkat D'Android, ils ont ajouté File[] getExternalFilesDirs (String type) dans la classe Context qui permet aux applications de stocker des données/fichiers dans des micro cartes SD.

Android 4.4 est la première version de la plate-forme cela a permis aux applications d'utiliser des cartes SD pour le stockage. Tout accès aux cartes SD avant le niveau 19 de L'API se faisait par le biais d'API privées et non supportées.

getExternalFilesDirs(String type) retourne les chemins absolus vers les répertoires spécifiques à l'application sur tous les périphériques de stockage partagés/externes. Cela signifie qu'il retournera les chemins vers la mémoire interne et externe. En général, second chemin retourné serait le chemin de stockage pour microSD carte (le cas échéant).

mais notez que,

stockage partagé peut ne pas toujours être disponible, car les supports amovibles peuvent être éjecté par l'utilisateur. L'état des médias peut être vérifié en utilisant getExternalStorageState(File) .

il n'y a pas de sécurité imposée avec ces fichiers. Par exemple, tout le support d'application WRITE_EXTERNAL_STORAGE peut écrire dans ces fichiers.

le stockage interne et externe terminologie selon Google / Docs Android officiel est tout à fait différent de ce que nous pensons.

4
répondu AnV 2017-09-22 12:59:28

Cette solution tient compte du fait que System.getenv("SECONDARY_STORAGE") ne sert à rien avec la guimauve.

testé et travaillant sur:

  • Samsung Galaxy Tab 2 (Android 4.1.1 - Stock)
  • Samsung Galaxy Note 8.0 (Android 4.2.2 - Stock)
  • Samsung Galaxy S4 (Android 4.4-Stock)
  • Samsung Galaxy S4 (Android 5.1.1-Cyanogenmod)
  • Samsung Galaxy Tab A (Android 6.0.1 - Stock)

    /**
     * Returns all available external SD-Card roots in the system.
     *
     * @return paths to all available external SD-Card roots in the system.
     */
    public static String[] getStorageDirectories() {
        String [] storageDirectories;
        String rawSecondaryStoragesStr = System.getenv("SECONDARY_STORAGE");
    
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            List<String> results = new ArrayList<String>();
            File[] externalDirs = applicationContext.getExternalFilesDirs(null);
            for (File file : externalDirs) {
                String path = file.getPath().split("/Android")[0];
                if((Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && Environment.isExternalStorageRemovable(file))
                        || rawSecondaryStoragesStr != null && rawSecondaryStoragesStr.contains(path)){
                    results.add(path);
                }
            }
            storageDirectories = results.toArray(new String[0]);
        }else{
            final Set<String> rv = new HashSet<String>();
    
            if (!TextUtils.isEmpty(rawSecondaryStoragesStr)) {
                final String[] rawSecondaryStorages = rawSecondaryStoragesStr.split(File.pathSeparator);
                Collections.addAll(rv, rawSecondaryStorages);
            }
            storageDirectories = rv.toArray(new String[rv.size()]);
        }
        return storageDirectories;
    }
    
3
répondu DaveAlden 2016-09-07 14:08:40

depuis ma réponse initiale ci-dessus, le moulage à balayage n'est plus viable chez les différents fabricants.

j'ai développé une méthode plus fiable et simple.

File mnt = new File("/storage");
if (!mnt.exists())
    mnt = new File("/mnt");

File[] roots = mnt.listFiles(new FileFilter() {

    @Override
    public boolean accept(File pathname) {
        return pathname.isDirectory() && pathname.exists()
                && pathname.canWrite() && !pathname.isHidden()
                && !isSymlink(pathname);
    }
});

roots contiendra tous les répertoires racine inscriptibles sur le système, y compris tous les périphériques usb connectés.

NOTE: la méthode canWrite nécessite l'android.autorisation.WRITE_EXTERNAL_STORAGE permission.

2
répondu Baron 2015-03-18 12:32:15

il était si tard, mais finalement j'ai obtenu quelque chose que j'ai testé la plupart des appareils( par le fabricant et les versions android) son travail sur Android 2.2+. si vous trouvez qu'il ne fonctionne pas, commentez-le avec le nom de votre périphérique. je vais le corriger. si quelqu'un est intéressé, je lui expliquerai comment cela fonctionne.

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStreamReader;

import android.util.Log;


/**
 * @author ajeet
 *05-Dec-2014  2014
 *
 */
public class StorageUtil {

    public boolean isRemovebleSDCardMounted() {
        File file = new File("/sys/class/block/");
        File[] files = file.listFiles(new MmcblkFilter("mmcblk\d$"));
        boolean flag = false;
        for (File mmcfile : files) {
            File scrfile = new File(mmcfile, "device/scr");
            if (scrfile.exists()) {
                flag = true;
                break;
            }
        }
        return flag;
    }

    public String getRemovebleSDCardPath() throws IOException {
        String sdpath = null;
        File file = new File("/sys/class/block/");
        File[] files = file.listFiles(new MmcblkFilter("mmcblk\d$"));
        String sdcardDevfile = null;
        for (File mmcfile : files) {
            Log.d("SDCARD", mmcfile.getAbsolutePath());
            File scrfile = new File(mmcfile, "device/scr");
            if (scrfile.exists()) {
                sdcardDevfile = mmcfile.getName();
                Log.d("SDCARD", mmcfile.getName());
                break;
            }
        }
        if (sdcardDevfile == null) {
            return null;
        }
        FileInputStream is;
        BufferedReader reader;

        files = file.listFiles(new MmcblkFilter(sdcardDevfile + "p\d+"));
        String deviceName = null;
        if (files.length > 0) {
            Log.d("SDCARD", files[0].getAbsolutePath());
            File devfile = new File(files[0], "dev");
            if (devfile.exists()) {
                FileInputStream fis = new FileInputStream(devfile);
                reader = new BufferedReader(new InputStreamReader(fis));
                String line = reader.readLine();
                deviceName = line;
            }
            Log.d("SDCARD", "" + deviceName);
            if (deviceName == null) {
                return null;
            }
            Log.d("SDCARD", deviceName);

            final File mountFile = new File("/proc/self/mountinfo");

            if (mountFile.exists()) {
                is = new FileInputStream(mountFile);
                reader = new BufferedReader(new InputStreamReader(is));
                String line = null;
                while ((line = reader.readLine()) != null) {
                    // Log.d("SDCARD", line);
                    // line = reader.readLine();
                    // Log.d("SDCARD", line);
                    String[] mPonts = line.split("\s+");
                    if (mPonts.length > 6) {
                        if (mPonts[2].trim().equalsIgnoreCase(deviceName)) {
                            if (mPonts[4].contains(".android_secure")
                                    || mPonts[4].contains("asec")) {
                                continue;
                            }
                            sdpath = mPonts[4];
                            Log.d("SDCARD", mPonts[4]);

                        }
                    }

                }
            }

        }

        return sdpath;
    }

    static class MmcblkFilter implements FilenameFilter {
        private String pattern;

        public MmcblkFilter(String pattern) {
            this.pattern = pattern;

        }

        @Override
        public boolean accept(File dir, String filename) {
            if (filename.matches(pattern)) {
                return true;
            }
            return false;
        }

    }

}
1
répondu Ajeet Khadke 2015-08-19 00:53:45

en écrivant le code ci-dessous vous obtiendrez l'emplacement:

/storage/663D-554E/Android/data/app_package_name/files/

qui stocke les données de votre application à l'emplacement /android/data à l'intérieur de la sd_card.

File[] list = ContextCompat.getExternalFilesDirs(MainActivity.this, null);

list[1]+"/fol" 

pour obtenir la position pass 0 pour interne et 1 pour sdcard au tableau de fichiers.

j'ai testé ce code sur une moto g4 plus et Samsung appareil (tout fonctionne très bien).

j'espère que cela pourrait être utile.

1
répondu Rk215 Tech 2018-05-31 21:18:46

Je ne sais pas pourquoi mais je dois appeler .createNewFile () sur un fichier créé dans les répertoires de stockage public avant de l'utiliser. Dans le cadre les commentaires pour cette méthode disent qu'elle n'est pas utile. Voici un échantillon...


 String myPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PODCASTS) + File.separator + "My Directory";
            final File myDir = new File(myPath);
            try {
                myDir.mkdirs();
            } catch (Exception ex) {
                Toast.makeText(this, "error: " + ex.getMessage(), Toast.LENGTH_LONG).show();
            }

        String fname = "whatever";
        File newFile = new File(myDir, fname);

        Log.i(TAG, "File exists --> " + newFile.exists()) //will be false  
    try {
            if (newFile.createNewFile()) {

                 //continue 

              } else {

                Log.e(TAG, "error creating file");

            }

        } catch (Exception e) {
            Log.e(TAG, e.toString());
        }

0
répondu user1743524 2015-03-25 16:25:58

j'ai créé une méthode utils pour vérifier qu'une carte SD est disponible sur le périphérique ou non, et obtenir le chemin de la carte SD sur le périphérique si elle est disponible.

vous pouvez copier 2 méthodes ci-dessous dans la classe de votre projet que vous avez besoin. C'est tout.

public String isRemovableSDCardAvailable() {
    final String FLAG = "mnt";
    final String SECONDARY_STORAGE = System.getenv("SECONDARY_STORAGE");
    final String EXTERNAL_STORAGE_DOCOMO = System.getenv("EXTERNAL_STORAGE_DOCOMO");
    final String EXTERNAL_SDCARD_STORAGE = System.getenv("EXTERNAL_SDCARD_STORAGE");
    final String EXTERNAL_SD_STORAGE = System.getenv("EXTERNAL_SD_STORAGE");
    final String EXTERNAL_STORAGE = System.getenv("EXTERNAL_STORAGE");

    Map<Integer, String> listEnvironmentVariableStoreSDCardRootDirectory = new HashMap<Integer, String>();
    listEnvironmentVariableStoreSDCardRootDirectory.put(0, SECONDARY_STORAGE);
    listEnvironmentVariableStoreSDCardRootDirectory.put(1, EXTERNAL_STORAGE_DOCOMO);
    listEnvironmentVariableStoreSDCardRootDirectory.put(2, EXTERNAL_SDCARD_STORAGE);
    listEnvironmentVariableStoreSDCardRootDirectory.put(3, EXTERNAL_SD_STORAGE);
    listEnvironmentVariableStoreSDCardRootDirectory.put(4, EXTERNAL_STORAGE);

    File externalStorageList[] = null;
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
        externalStorageList = getContext().getExternalFilesDirs(null);
    }
    String directory = null;
    int size = listEnvironmentVariableStoreSDCardRootDirectory.size();
    for (int i = 0; i < size; i++) {
        if (externalStorageList != null && externalStorageList.length > 1 && externalStorageList[1] != null)
            directory = externalStorageList[1].getAbsolutePath();
        else
            directory = listEnvironmentVariableStoreSDCardRootDirectory.get(i);

        directory = canCreateFile(directory);
        if (directory != null && directory.length() != 0) {
            if (i == size - 1) {
                if (directory.contains(FLAG)) {
                    Log.e(getClass().getSimpleName(), "SD Card's directory: " + directory);
                    return directory;
                } else {
                    return null;
                }
            }
            Log.e(getClass().getSimpleName(), "SD Card's directory: " + directory);
            return directory;
        }
    }
    return null;
}

/**
 * Check if can create file on given directory. Use this enclose with method
 * {@link BeginScreenFragement#isRemovableSDCardAvailable()} to check sd
 * card is available on device or not.
 * 
 * @param directory
 * @return
 */
public String canCreateFile(String directory) {
    final String FILE_DIR = directory + File.separator + "hoang.txt";
    File tempFlie = null;
    try {
        tempFlie = new File(FILE_DIR);
        FileOutputStream fos = new FileOutputStream(tempFlie);
        fos.write(new byte[1024]);
        fos.flush();
        fos.close();
        Log.e(getClass().getSimpleName(), "Can write file on this directory: " + FILE_DIR);
    } catch (Exception e) {
        Log.e(getClass().getSimpleName(), "Write file error: " + e.getMessage());
        return null;
    } finally {
        if (tempFlie != null && tempFlie.exists() && tempFlie.isFile()) {
            // tempFlie.delete();
            tempFlie = null;
        }
    }
    return directory;
}
0
répondu user3161772 2015-11-30 07:12:58

son travail pour tous les périphériques externes, mais assurez-vous seulement obtenir le nom de dossier périphérique externe et ensuite vous devez obtenir le fichier à partir d'un emplacement donné en utilisant la classe de fichier.

public static List<String> getExternalMounts() {
        final List<String> out = new ArrayList<>();
        String reg = "(?i).*vold.*(vfat|ntfs|exfat|fat32|ext3|ext4).*rw.*";
        String s = "";
        try {
            final Process process = new ProcessBuilder().command("mount")
                    .redirectErrorStream(true).start();
            process.waitFor();
            final InputStream is = process.getInputStream();
            final byte[] buffer = new byte[1024];
            while (is.read(buffer) != -1) {
                s = s + new String(buffer);
            }
            is.close();
        } catch (final Exception e) {
            e.printStackTrace();
        }

        // parse output
        final String[] lines = s.split("\n");
        for (String line : lines) {
            if (!line.toLowerCase(Locale.US).contains("asec")) {
                if (line.matches(reg)) {
                    String[] parts = line.split(" ");
                    for (String part : parts) {
                        if (part.startsWith("/"))
                            if (!part.toLowerCase(Locale.US).contains("vold"))
                                out.add(part);
                    }
                }
            }
        }
        return out;
    }

appel:

List<String> list=getExternalMounts();
        if(list.size()>0)
        {
            String[] arr=list.get(0).split("/");
            int size=0;
            if(arr!=null && arr.length>0) {
                size= arr.length - 1;
            }
            File parentDir=new File("/storage/"+arr[size]);
            if(parentDir.listFiles()!=null){
                File parent[] = parentDir.listFiles();

                for (int i = 0; i < parent.length; i++) {

                    // get file path as parent[i].getAbsolutePath());

                }
            }
        }

accès au stockage externe

pour lire ou écrire des fichiers sur le stockage externe, votre application doit acquérir le READ_EXTERNAL_STORAGE ou WRITE_EXTERNAL_STORAGE permissions système. Par exemple:

<manifest ...>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    ...
</manifest>
-1
répondu Neeraj Singh 2017-07-21 06:29:02

/sdcard => Stockage interne (c'est un lien symbolique mais cela devrait fonctionner)

/mnt / extSdCard => External Sdcard

C'est pour Samsung Galaxy S3

vous pouvez probablement compter sur ce qui est vrai pour la plupart...vérifiez toutefois!

-2
répondu robbyoconnor 2016-02-05 06:06:17