Znajdź lokalizację zewnętrznej karty SD

Czy istnieje uniwersalny sposób na znalezienie lokalizacji zewnętrznej karty SD?

Proszę nie mylić z zewnętrzną pamięcią masową . Environment.getExternalStorageState() zwraca ścieżkę do wewnętrznego punktu montowania SD jak "/ mnt / sdcard". Ale pytanie dotyczy zewnętrznego SD. Jak uzyskać ścieżkę typu " / mnt / sdcard / external_sd "(może się różnić w zależności od urządzenia)?

Chyba zakończę filtrowaniem komendy mount po nazwie systemu plików. Ale nie jestem pewien, czy ten sposób jest wystarczająco wytrzymały.

Author: Lightness Races in Orbit, 2011-04-17

20 answers

Environment.getExternalStorageState() zwraca ścieżkę do wewnętrznego punktu montowania SD jak "/ mnt / sdcard "

Nie, Environment.getExternalStorageDirectory() odnosi się do tego, co producent urządzenia uznał za "pamięć zewnętrzną". Na niektórych urządzeniach są to nośniki wymienne, takie jak karta SD. Na niektórych urządzeniach jest to część pamięci flash urządzenia. W tym przypadku "pamięć zewnętrzna" oznacza "rzeczy dostępne w trybie pamięci masowej USB po zamontowaniu na komputerze hosta", przynajmniej dla systemu Android 1.x i 2.x.

Ale pytanie jest o zewnętrzny SD. Jak uzyskać ścieżkę typu " / mnt / sdcard / external_sd "(może się różnić w zależności od urządzenia)?

Android nie ma pojęcia "zewnętrznej pamięci SD", poza zewnętrzną pamięcią masową, jak opisano powyżej.

Jeśli producent urządzenia zdecydował się na zewnętrzną pamięć flash na pokładzie, a także ma kartę SD, musisz skontaktować się z tym producentem, aby ustalić, czy możesz używać karty SD (nie gwarantowane) i jakie są zasady jej używania, takie jak ścieżka użycia za to.


UPDATE

Dwie ostatnie rzeczy:

Po pierwsze, na Androidzie 4.4+, nie masz dostępu do zapisu na nośnikach wymiennych( np. "zewnętrzne SD"), z wyjątkiem miejsc na tym nośniku, które mogą być zwracane przez getExternalFilesDirs() i getExternalCacheDirs(). Zobacz doskonałą analizę Dave ' a Smitha tego, szczególnie jeśli chcesz poznać szczegóły niskiego poziomu.

Po drugie, aby nikt nie spierał się, czy dostęp do nośników wymiennych jest w inny sposób częścią Android SDK, tutaj jest ocena Dianne Hackborn :

...należy pamiętać: do Androida 4.4, oficjalna platforma Android nie obsługiwała kart SD w wszystkie Z wyjątkiem dwóch szczególnych przypadków: układ starej szkoły pamięci masowej, gdzie pamięć zewnętrzna jest kartą SD (która jest nadal obsługiwana przez platformę dzisiaj), i mała funkcja dodana do Androida 3.0, gdzie skanuje dodatkowe karty SD i dodaje je do dostawcy mediów i daje aplikacjom dostęp tylko do odczytu ich plików (co jest również do dziś wspierane w platformie).

Android 4.4 jest pierwszym wydaniem platformy, która faktycznie pozwoliła aplikacjom używać kart SD do przechowywania. Dostęp do nich był możliwy przez prywatne, nieobsługiwane interfejsy API. Mamy teraz dość bogate API na platformie, która pozwala aplikacjom na korzystanie z kart SD w obsługiwany sposób, w lepszy sposób niż były w stanie wcześniej: mogą bezpłatnie korzystać z obszaru pamięci specyficznej dla aplikacji, bez konieczności stosowania jakichkolwiek uprawnienia w aplikacji i może uzyskać dostęp do innych plików na karcie SD, tak długo, jak przechodzą przez selektor plików, ponownie bez potrzeby żadnych specjalnych uprawnień.

 147
Author: CommonsWare,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-11 13:03:57

Wymyśliłem następujące rozwiązanie na podstawie kilku odpowiedzi znalezionych tutaj.

Kod:

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;
    }
}

Użycie:

Map<String, File> externalLocations = ExternalStorage.getAllStorageLocations();
File sdCard = externalLocations.get(ExternalStorage.SD_CARD);
File externalSdCard = externalLocations.get(ExternalStorage.EXTERNAL_SD_CARD);
 60
Author: Richard,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-10 02:41:40

Miałem aplikację, która używała ListPreference gdzie użytkownik musiał wybrać lokalizację, w której chciał coś zapisać. W tej aplikacji zeskanowałem /proc / mounts i / system / etc / vold.fstab dla punktów montowania sdcard. Zapisałem punkty montowania z KAŻDEGO pliku w dwóch oddzielnych ArrayList s.

Następnie porównałem jedną listę z drugą i odrzuciłem elementy, których nie było na obu listach. To dało mi listę ścieżek Głównych do każdej karty SD.

Stamtąd przetestowałem ścieżki z File.exists(), File.isDirectory() i File.canWrite(). Jeśli któryś z tych testów był fałszywy, odrzuciłem tę ścieżkę z listy.

Cokolwiek zostało na liście, przekonwertowałem do tablicy String[], aby mogła być używana przez atrybut ListPreference values.

Możesz zobaczyć kod tutaj: http://sapienmobile.com/?p=204

 36
Author: Baron,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-15 02:02:52

W celu pobrania wszystkich zewnętrznych magazynów (czy są karty SD lub wewnętrzne nieusuwalne magazyny), możesz użyć następującego kodu:

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");
            }
        }
    }
}

Alternatywnie możesz użyć systemu.getenv ("EXTERNAL_STORAGE") , aby pobrać główny zewnętrzny katalog pamięci (np. "/storage/sdcard0") i System .getenv ("SECONDARY_STORAGE") to retive the list of all the secondary Directory (e. g. W tym celu należy wykonać następujące czynności: Pamiętaj, że również w tym przypadku możesz filtrować listę wtórnych katalogów, aby wykluczyć napędy USB.

W każdym razie należy pamiętać, że używanie mocno zakodowanych ścieżek jest zawsze złym podejściem (szczególnie, gdy każdy producent może zmienić je według uznania).

 17
Author: Paolo Rovelli,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-07 14:03:36

Możesz spróbować użyć funkcji biblioteki wsparcia o nazwie 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());

Pierwsza z nich jest podstawową zewnętrzną pamięcią masową, a reszta ma być prawdziwymi ścieżkami kart SD.

Powód wielokrotności".getParentFile () " ma przejść do innego folderu, ponieważ oryginalna ścieżka to

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

EDIT: oto bardziej obszerny sposób, który stworzyłem, aby uzyskać ścieżki kart sd:

  /**
   * 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
Author: android developer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-15 07:46:43

Podobnie jak Richard używam pliku / proc / mounts aby uzyskać listę dostępnych opcji przechowywania

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
Author: Vitaliy Polchuk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-14 16:03:48

Można znaleźć miejsce zamontowania dodatkowych kart SD, odczytując /proc/mounts (standardowy plik Linuksa) i porównując dane vold (/system/etc/vold.conf). I zauważ, że lokalizacja zwracana przez Environment.getExternalStorageDirectory() może nie pojawić się w konfiguracji vold (w niektórych urządzeniach jest to pamięć wewnętrzna, której nie można odmontować), ale nadal musi być uwzględniona na liście. Jednak nie znaleźliśmy dobrego sposobu, aby opisać je użytkownikowi.

 10
Author: Jan Hudec,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:26:27

Tym razem wypróbuję wszystkie rozwiązania w tym temacie. Ale wszystkie z nich nie działały poprawnie na urządzeniach z jedną zewnętrzną (wymienną) i jedną wewnętrzną (Nie-wymienną) kartą. Ścieżka do zewnętrznej karty nie jest możliwa Pobierz z polecenia 'mount', z pliku 'proc/mounts' itd.

I tworzę swoje własne rozwiązanie (na temat Paulo Luana):

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
Author: Tapa Save,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-19 00:55:39

Po prostu użyj tego:

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
Author: ray pixar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-08 05:23:48

Jeśli spojrzysz na kod źródłowy android.os.Environment zobaczysz, że Android w dużym stopniu opiera się na zmiennych środowiskowych dla ścieżek. Możesz użyć zmiennej środowiskowej" SECONDARY_STORAGE", aby znaleźć ścieżkę do wymiennej karty sd.

/**
 * 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;
}

Przykładowe użycie:

public static final File REMOVABLE_STORAGE = getDirectory("SECONDARY_STORAGE");
 5
Author: Jared Rummler,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-07 21:59:31

Oto sposób, w jaki znajduję zewnętrzną kartę. Użyj mount cmd return, a następnie przeanalizuj część 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
Author: Fakebear,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-23 02:25:14

Czy istnieje uniwersalny sposób na znalezienie lokalizacji zewnętrznej karty SD?

Przez uniwersalną drogę , jeśli masz na myśli oficjalną drogę; tak, jest jedna.

Na poziomie API 19, tj. w Androidzie w wersji 4.4 Kitkat, dodali File[] getExternalFilesDirs (String type) w klasie Context, która umożliwia aplikacjom przechowywanie danych / plików na kartach micro SD.

Android 4.4 jest pierwszym wydaniem platformy, która pozwoliła aplikacjom używać kart SD do przechowywania danych. Dostęp do kart SD przed poziomem API 19 przez prywatne, nieobsługiwane API.

GetExternalFilesDirs (typ String) zwraca bezwzględne ścieżki do katalogów specyficznych dla aplikacji na wszystkich współdzielonych / zewnętrznych urządzeniach pamięci masowej. Oznacza to, że zwróci ścieżki zarówno do pamięci wewnętrznej, jak i zewnętrznej. Ogólnie rzecz biorąc, druga ścieżka zwracana będzie ścieżką pamięci dla karty microSD (jeśli istnieje).

Ale zauważ, że

Współdzielona pamięć masowa może nie zawsze być dostępna, ponieważ nośniki wymienne mogą być wyrzucony przez użytkownik. Stan nośnika można sprawdzić za pomocą getExternalStorageState(File).

Z tymi plikami nie ma żadnych zabezpieczeń. Na przykład, każdy application holding WRITE_EXTERNAL_STORAGE może zapisywać do tych plików.

Wewnętrzna i Zewnętrzna pamięć masowa terminologia Według Google/official Android docs jest zupełnie inna od tego, co myślimy.

 4
Author: AnV,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-22 12:59:28

To rozwiązanie obsługuje fakt, że {[1] } jest bezużyteczny z prawoślazu.

Przetestowane i działające na:

  • 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
Author: DaveAlden,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-07 14:08:40

Od mojej pierwotnej odpowiedzi powyżej, skanowanie vold nie jest już wykonalne w różnych producentów.

Opracowałem bardziej niezawodną i prostą metodę.

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 będzie zawierał wszystkie zapisywalne katalogi główne w systemie, w tym wszystkie podłączone do usb urządzenia usb.

Uwaga: metoda canWrite wymaga Androida.pozwolenie.Uprawnienia WRITE_EXTERNAL_STORAGE.

 2
Author: Baron,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-18 12:32:15

Było tak późno, ale w końcu dostałem coś przetestowałem większość urządzeń (według wersji producenta i Androida) działa na Androidzie 2.2+. jeśli okaże się, że nie działa, skomentuj go nazwą urządzenia. naprawię to. jeśli ktoś zainteresowany wyjaśnię jak to działa.

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
Author: Ajeet Khadke,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-19 00:53:45

Pisząc poniższy kod otrzymasz lokalizację:

/storage / 663d-554e/Android/data/app_package_name/files /

Który przechowuje dane aplikacji w lokalizacji / android / data wewnątrz karty SD.

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

list[1]+"/fol" 

Dla uzyskania lokalizacji pass 0 dla wewnętrznej i 1 dla sdcard do tablicy plików.

Przetestowałem ten kod na urządzeniu moto G4 plus i Samsung (wszystko działa dobrze).

Mam nadzieję, że to pomoże.
 1
Author: Rk215 Tech,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-31 21:18:46

Nie wiem dlaczego, ale muszę zadzwonić .createNewFile () na pliku utworzonym w katalogach magazynu publicznego przed jej użyciem. W frameworku komentarze do tej metody mówią, że nie jest przydatna. Oto próbka...


 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
Author: user1743524,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-25 16:25:58

Stworzyłem metodę utils, aby sprawdzić, czy karta SD jest dostępna na urządzeniu, czy nie, i uzyskać ścieżkę karty SD na urządzeniu, jeśli jest dostępna.

Możesz skopiować poniżej 2 metody do klasy twojego projektu, której potrzebujesz. To wszystko.

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
Author: user3161772,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-30 07:12:58

Działa dla wszystkich zewnętrznych urządzeń, ale upewnij się, że uzyskasz tylko nazwę folderu zewnętrznego urządzenia, a następnie musisz pobrać plik z podanej lokalizacji za pomocą klasy File.

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;
    }

Wywołanie:

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());

                }
            }
        }

Uzyskiwanie dostępu do pamięci zewnętrznej

Aby odczytywać lub zapisywać pliki na zewnętrznej pamięci masowej, aplikacja musi uzyskać uprawnienia systemowe READ_EXTERNAL_STORAGElub WRITE_EXTERNAL_STORAGE. Na przykład:

<manifest ...>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    ...
</manifest>
 -1
Author: Neeraj Singh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-21 06:29:02

/sdcard = > Pamięć wewnętrzna (jest to dowiązanie symboliczne, ale powinno działać)

/ mnt / extSdCard = > External Sdcard

To jest dla Samsung Galaxy S3

Prawdopodobnie możesz liczyć na to, że to prawda dla większości...sprawdź jeszcze raz!

 -2
Author: robbyoconnor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-05 06:06:17