Как я могу получить внешний путь SD-карты для Android 4.0+?

Samsung Galaxy S3 имеет слот для карт памяти Extrenal SD, который установлен на /mnt/extSdCard.

Мой вопрос: как получить этот путь чем-то вроде Environment.getExternalStorageDirectory()? Это вернет mnt/sdcard, и я не могу найти API для внешней SD-карты. (Или съемное USB-накопитель на некоторых планшетах)

Спасибо!

Ответ 1

У меня есть вариация на решение, которое я нашел здесь

public static HashSet<String> getExternalMounts() {
    final HashSet<String> out = new HashSet<String>();
    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;
}

Оригинальный метод был протестирован и работал с

  • Huawei X3 (запас)
  • Galaxy S2 (запас)
  • Galaxy S3 (запас)

Я не уверен, какая версия для Android была включена, когда они были протестированы.

Я тестировал измененную версию с помощью

  • Moto Xoom 4.1.2 (запас)
  • Galaxy Nexus (cyanogenmod 10) с использованием кабеля otg
  • HTC Incredible (cyanogenmod 7.2) возвращает как внутренние, так и внешние. Это устройство является чем-то странным в том, что его внутренняя часть в основном не используется, поскольку getExternalStorage() возвращает путь к SD-карте.

и некоторые отдельные устройства хранения, которые используют sdcard в качестве основного хранилища

  • HTC G1 (cyanogenmod 6.1)
  • HTC G1 (запас)
  • HTC Vision/G2 (запас)

За исключением Incredible все эти устройства только вернули свое съемное хранилище. Вероятно, есть некоторые дополнительные проверки, которые я должен делать, но это, по крайней мере, немного лучше любого решения, которое я нашел до сих пор.

Ответ 2

Я нашел более надежный способ получить пути ко всем SD-CARD в системе. Это работает на всех версиях Android и возвращает пути ко всем хранилищам (включая эмулирование).

Работает правильно на всех моих устройствах.

P.S.: На основе исходного кода класса среды.

private static final Pattern DIR_SEPORATOR = Pattern.compile("/");

/**
 * Raturns all available SD-Cards in the system (include emulated)
 *
 * Warning: Hack! Based on Android source code of version 4.3 (API 18)
 * Because there is no standart way to get it.
 * TODO: Test on future Android versions 4.4+
 *
 * @return paths to all available SD-Cards in the system (include emulated)
 */
public static String[] getStorageDirectories()
{
    // Final set of paths
    final Set<String> rv = new HashSet<String>();
    // Primary physical SD-CARD (not emulated)
    final String rawExternalStorage = System.getenv("EXTERNAL_STORAGE");
    // All Secondary SD-CARDs (all exclude primary) separated by ":"
    final String rawSecondaryStoragesStr = System.getenv("SECONDARY_STORAGE");
    // Primary emulated SD-CARD
    final String rawEmulatedStorageTarget = System.getenv("EMULATED_STORAGE_TARGET");
    if(TextUtils.isEmpty(rawEmulatedStorageTarget))
    {
        // Device has physical external storage; use plain paths.
        if(TextUtils.isEmpty(rawExternalStorage))
        {
            // EXTERNAL_STORAGE undefined; falling back to default.
            rv.add("/storage/sdcard0");
        }
        else
        {
            rv.add(rawExternalStorage);
        }
    }
    else
    {
        // Device has emulated storage; external storage paths should have
        // userId burned into them.
        final String rawUserId;
        if(Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1)
        {
            rawUserId = "";
        }
        else
        {
            final String path = Environment.getExternalStorageDirectory().getAbsolutePath();
            final String[] folders = DIR_SEPORATOR.split(path);
            final String lastFolder = folders[folders.length - 1];
            boolean isDigit = false;
            try
            {
                Integer.valueOf(lastFolder);
                isDigit = true;
            }
            catch(NumberFormatException ignored)
            {
            }
            rawUserId = isDigit ? lastFolder : "";
        }
        // /storage/emulated/0[1,2,...]
        if(TextUtils.isEmpty(rawUserId))
        {
            rv.add(rawEmulatedStorageTarget);
        }
        else
        {
            rv.add(rawEmulatedStorageTarget + File.separator + rawUserId);
        }
    }
    // Add all secondary storages
    if(!TextUtils.isEmpty(rawSecondaryStoragesStr))
    {
        // All Secondary SD-CARDs splited into array
        final String[] rawSecondaryStorages = rawSecondaryStoragesStr.split(File.pathSeparator);
        Collections.addAll(rv, rawSecondaryStorages);
    }
    return rv.toArray(new String[rv.size()]);
}

Ответ 3

Я предполагаю использовать внешнюю SD-карту, которую вы должны использовать:

new File("/mnt/external_sd/")

ИЛИ

new File("/mnt/extSdCard/")

в вашем случае...

вместо Environment.getExternalStorageDirectory()

Работает для меня. Вы должны сначала проверить, что находится в каталоге mnt, и работать там.


Вы должны использовать некоторый тип метода выбора, чтобы выбрать, какую SDCard использовать:

File storageDir = new File("/mnt/");
if(storageDir.isDirectory()){
    String[] dirList = storageDir.list();
    //TODO some type of selecton method?
}

Ответ 4

Чтобы получить все внешние хранилища

В качестве альтернативы вы можете использовать System.getenv( "EXTERNAL_STORAGE" ) для извлечения основного каталога внешнего хранилища (например, "/storage/sdcard0" ) и System.getenv( "SECONDARY_STORAGE" ) ), чтобы получить список всех вторичных каталогов (например, "/storage/extSdCard:/storage/UsbDriveA:/storage/UsbDriveB" ). Помните, что в этом случае вам может понадобиться отфильтровать список вторичных каталогов, чтобы исключить USB-диски.

В любом случае, обратите внимание, что использование жестко закодированных путей всегда является плохим подходом (особенно когда каждый производитель может изменить его как приятно).

Ответ 5

Я использовал решение Дмитрия Лозенко, пока не проверил на Asus Zenfone2, Marshmallow 6.0.1, и решение не работает. Решение не получилось при получении EMULATED_STORAGE_TARGET, в частности, для пути microSD, например: /storage/F99C-10F4/. Я отредактировал код, чтобы получить эмулированные корневые пути непосредственно из эмулируемых путей приложения с помощью context.getExternalFilesDirs(null); и добавить более известные физические пути для конкретной модели телефона.

Чтобы сделать нашу жизнь проще, я создал библиотеку здесь. Вы можете использовать его через систему построения градиентов, maven, sbt и leiningen.

Если вам нравится старомодный способ, вы также можете скопировать вставить файл прямо здесь, но вы не узнаете, есть ли обновление в будущем, не проверив его вручную.

Если у вас есть какие-либо вопросы или предложения, пожалуйста, сообщите мне

Ответ 6

Хорошие новости! В KitKat теперь есть общедоступный API для взаимодействия с этими дополнительными совместно используемыми устройствами хранения.

Новые методы Context.getExternalFilesDirs() и Context.getExternalCacheDirs() могут возвращать несколько путей, включая как первичные, так и вторичные устройства. Затем вы можете перебрать их и проверить Environment.getStorageState() и File.getFreeSpace(), чтобы определить наилучшее место для хранения ваших файлов. Эти методы также доступны на ContextCompat в библиотеке support-v4.

Также обратите внимание, что если вы заинтересованы в использовании каталогов, возвращаемых Context, вам больше не нужны разрешения READ_ или WRITE_EXTERNAL_STORAGE. В будущем вы всегда будете иметь доступ на чтение/запись к этим каталогам без каких-либо дополнительных разрешений.

Приложения также могут продолжить работу над более старыми устройствами, выполнив их запрос на разрешение следующим образом:

<uses-permission
    android:name="android.permission.WRITE_EXTERNAL_STORAGE"
    android:maxSdkVersion="18" />

Ответ 7

Я сделал следующее, чтобы получить доступ ко всем внешним SD-картам.

С

File primaryExtSd=Environment.getExternalStorageDirectory();

вы получаете путь к основному внешнему SD Затем с помощью:

File parentDir=new File(primaryExtSd.getParent());

вы получаете родительский каталог первичного внешнего хранилища, а также родительский элемент внешнего внешнего sd. Теперь вы можете перечислить все хранилище и выбрать тот, который вы хотите.

Надеюсь, что это полезно.

Ответ 8

Вот как я получаю список путей 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;
      }
    }

Ответ 9

Спасибо за подсказки, предоставленные вами, ребята, особенно @SmartLemon, я получил решение. В случае, если кому-то это понадобится, я поставил свое окончательное решение здесь (чтобы найти первую указанную внешнюю SD-карту):

public File getExternalSDCardDirectory()
{
    File innerDir = Environment.getExternalStorageDirectory();
    File rootDir = innerDir.getParentFile();
    File firstExtSdCard = innerDir ;
    File[] files = rootDir.listFiles();
    for (File file : files) {
        if (file.compareTo(innerDir) != 0) {
            firstExtSdCard = file;
            break;
        }
    }
    //Log.i("2", firstExtSdCard.getAbsolutePath().toString());
    return firstExtSdCard;
}

Если на карте нет внешней SD-карты, она возвращает память на борту. Я буду использовать его, если sdcard не существует, возможно, вам придется его изменить.

Ответ 10

обратитесь к моему коду, надейтесь на помощь:

    Runtime runtime = Runtime.getRuntime();
    Process proc = runtime.exec("mount");
    InputStream is = proc.getInputStream();
    InputStreamReader isr = new InputStreamReader(is);
    String line;
    String mount = new String();
    BufferedReader br = new BufferedReader(isr);
    while ((line = br.readLine()) != null) {
        if (line.contains("secure")) continue;
        if (line.contains("asec")) continue;

        if (line.contains("fat")) {//TF card
            String columns[] = line.split(" ");
            if (columns != null && columns.length > 1) {
                mount = mount.concat("*" + columns[1] + "\n");
            }
        } else if (line.contains("fuse")) {//internal storage
            String columns[] = line.split(" ");
            if (columns != null && columns.length > 1) {
                mount = mount.concat(columns[1] + "\n");
            }
        }
    }
    txtView.setText(mount);

Ответ 11

На самом деле в некоторых устройствах внешнее имя по умолчанию sdcard отображается как extSdCard, а для другого - sdcard1.

Этот фрагмент кода помогает узнать этот точный путь и помогает найти путь к внешнему устройству.

String sdpath,sd1path,usbdiskpath,sd0path;    
        if(new File("/storage/extSdCard/").exists())
            {
               sdpath="/storage/extSdCard/";
               Log.i("Sd Cardext Path",sdpath);
            }
        if(new File("/storage/sdcard1/").exists())
         {
              sd1path="/storage/sdcard1/";
              Log.i("Sd Card1 Path",sd1path);
         }
        if(new File("/storage/usbcard1/").exists())
         {
              usbdiskpath="/storage/usbcard1/";
              Log.i("USB Path",usbdiskpath);
         }
        if(new File("/storage/sdcard0/").exists())
         {
              sd0path="/storage/sdcard0/";
              Log.i("Sd Card0 Path",sd0path);
         }

Ответ 12

Да. Различные производители используют другое имя SDcard, как в Samsung Tab 3, его extsd, а другие устройства samsung используют sdcard, так как этот другой производитель использует разные имена.

У меня было такое же требование, как и вы. поэтому я создал образец примера для вас из моего проекта, перейдя по ссылке Android Directory chooser, в которой используется библиотека androi-dirchooser. В этом примере обнаруживается SD-карта и список всех подпапок, а также определяется, имеет ли устройство более одну SD-карту.

Часть кода выглядит так. Для полного примера перейдите по ссылке Android Directory chooser

/**
* Returns the path to internal storage ex:- /storage/emulated/0
 *
* @return
 */
private String getInternalDirectoryPath() {
return Environment.getExternalStorageDirectory().getAbsolutePath();
 }

/**
 * Returns the SDcard storage path for samsung ex:- /storage/extSdCard
 *
 * @return
 */
    private String getSDcardDirectoryPath() {
    return System.getenv("SECONDARY_STORAGE");
}


 mSdcardLayout.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View view) {
        String sdCardPath;
        /***
         * Null check because user may click on already selected buton before selecting the folder
         * And mSelectedDir may contain some wrong path like when user confirm dialog and swith back again
         */

        if (mSelectedDir != null && !mSelectedDir.getAbsolutePath().contains(System.getenv("SECONDARY_STORAGE"))) {
            mCurrentInternalPath = mSelectedDir.getAbsolutePath();
        } else {
            mCurrentInternalPath = getInternalDirectoryPath();
        }
        if (mCurrentSDcardPath != null) {
            sdCardPath = mCurrentSDcardPath;
        } else {
            sdCardPath = getSDcardDirectoryPath();
        }
        //When there is only one SDcard
        if (sdCardPath != null) {
            if (!sdCardPath.contains(":")) {
                updateButtonColor(STORAGE_EXTERNAL);
                File dir = new File(sdCardPath);
                changeDirectory(dir);
            } else if (sdCardPath.contains(":")) {
                //Multiple Sdcards show root folder and remove the Internal storage from that.
                updateButtonColor(STORAGE_EXTERNAL);
                File dir = new File("/storage");
                changeDirectory(dir);
            }
        } else {
            //In some unknown scenario at least we can list the root folder
            updateButtonColor(STORAGE_EXTERNAL);
            File dir = new File("/storage");
            changeDirectory(dir);
        }


    }
});

Ответ 13

Это решение (собранное из других ответов на этот вопрос) обрабатывает факт (как упоминалось в @ono), что System.getenv("SECONDARY_STORAGE") бесполезен с Marshmallow.

Протестировано и работает над:

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

Ответ 14

На некоторых устройствах (например, samsung galaxy sII) внутренняя карта памяти mabe находится в vfat. В этом случае используйте последний код, мы получим карту внутренней карты пути (/mnt/sdcad), но не внешнюю карту. Код, приведенный ниже, решает эту проблему.

static String getExternalStorage(){
         String exts =  Environment.getExternalStorageDirectory().getPath();
         try {
            FileReader fr = new FileReader(new File("/proc/mounts"));       
            BufferedReader br = new BufferedReader(fr);
            String sdCard=null;
            String line;
            while((line = br.readLine())!=null){
                if(line.contains("secure") || line.contains("asec")) continue;
            if(line.contains("fat")){
                String[] pars = line.split("\\s");
                if(pars.length<2) continue;
                if(pars[1].equals(exts)) continue;
                sdCard =pars[1]; 
                break;
            }
        }
        fr.close();
        br.close();
        return sdCard;  

     } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return null;
}

Ответ 15

       File[] files = null;
    File file = new File("/storage");// /storage/emulated
if (file.exists()) {
        files = file.listFiles();
            }
            if (null != files)
                for (int j = 0; j < files.length; j++) {
                    Log.e(TAG, "" + files[j]);
                    Log.e(TAG, "//--//--// " +             files[j].exists());

                    if (files[j].toString().replaceAll("_", "")
                            .toLowerCase().contains("extsdcard")) {
                        external_path = files[j].toString();
                        break;
                    } else if (files[j].toString().replaceAll("_", "")
                            .toLowerCase()
                            .contains("sdcard".concat(Integer.toString(j)))) {
                        // external_path = files[j].toString();
                    }
                    Log.e(TAG, "--///--///--  " + external_path);
                }

Ответ 16

что не верно. /mnt/sdcard/external _sd может существовать, даже если SD-карта не установлена. ваше приложение выйдет из строя, когда вы попытаетесь записать в /mnt/sdcard/external _sd, когда он не установлен.

вам нужно сначала проверить, установлена ​​ли SD-карта, используя:

boolean isSDPresent = Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);

Ответ 17

Я уверен, что этот код наверняка решит ваши проблемы... Это отлично работает для меня... \

try {
            File mountFile = new File("/proc/mounts");
            usbFoundCount=0;
            sdcardFoundCount=0;
            if(mountFile.exists())
             {
                Scanner usbscanner = new Scanner(mountFile);
                while (usbscanner.hasNext()) {
                    String line = usbscanner.nextLine();
                    if (line.startsWith("/dev/fuse /storage/usbcard1")) {
                        usbFoundCount=1;
                        Log.i("-----USB--------","USB Connected and properly mounted---/dev/fuse /storage/usbcard1" );
                    }
            }
         }
            if(mountFile.exists()){
                Scanner sdcardscanner = new Scanner(mountFile);
                while (sdcardscanner.hasNext()) {
                    String line = sdcardscanner.nextLine();
                    if (line.startsWith("/dev/fuse /storage/sdcard1")) {
                        sdcardFoundCount=1;
                        Log.i("-----USB--------","USB Connected and properly mounted---/dev/fuse /storage/sdcard1" );
                    }
            }
         }
            if(usbFoundCount==1)
            {
                Toast.makeText(context,"USB Connected and properly mounted", 7000).show();
                Log.i("-----USB--------","USB Connected and properly mounted" );
            }
            else
            {
                Toast.makeText(context,"USB not found!!!!", 7000).show();
                Log.i("-----USB--------","USB not found!!!!" );

            }
            if(sdcardFoundCount==1)
            {
                Toast.makeText(context,"SDCard Connected and properly mounted", 7000).show();
                Log.i("-----SDCard--------","SDCard Connected and properly mounted" );
            }
            else
            {
                Toast.makeText(context,"SDCard not found!!!!", 7000).show();
                Log.i("-----SDCard--------","SDCard not found!!!!" );

            }
        }catch (Exception e) {
            e.printStackTrace();
        } 

Ответ 18

Для доступа к файлам на SD-карте, на моем HTC One X (Android), я использую этот путь:

file:///storage/sdcard0/folder/filename.jpg

Обратите внимание на триплекс "/"!

Ответ 19

 String path = Environment.getExternalStorageDirectory()
                        + File.separator + Environment.DIRECTORY_PICTURES;
                File dir = new File(path);

Ответ 20

Вы можете использовать что-то вроде Context.getExternalCacheDirs() или Context.getExternalFilesDirs() или Context.getObbDirs(). Они предоставляют конкретные каталоги приложений во всех внешних устройствах хранения, где приложение может хранить свои файлы.

Так что-то вроде этого: Context.getExternalCacheDirs() [i].getParentFile(). getParentFile(). getParentFile(). getParent() может получить корневой путь внешних устройств хранения.

Я знаю, что эти команды предназначены для другой цели, но другие ответы мне не помогли.

Эта ссылка дала мне хорошие указатели - https://possiblemobile.com/2014/03/android-external-storage/

Ответ 21

System.getenv("SECONDARY_STORAGE") возвращает значение null для Marshmallow. Это еще один способ найти все внешние источники. Вы можете проверить, является ли он съемным, который определяет, будет ли внутренний/внешний

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    File[] externalCacheDirs = context.getExternalCacheDirs();
    for (File file : externalCacheDirs) {
        if (Environment.isExternalStorageRemovable(file)) {
            // It a removable storage
        }
    }
}

Ответ 22

String secStore = System.getenv("SECONDARY_STORAGE");

File externalsdpath = new File(secStore);

Это даст путь к внешнему вторичному хранилищу sd.

Ответ 23

Я пробовал решения, предоставленные Дмитрием Лозенко и Gnathonic на моей вкладке Samsung Galaxy Tab S2 (модель: T819Y), но никто не помог мне найдите путь к внешнему каталогу SD-карты. Выполнение команды mount содержало необходимый путь к каталогу внешней SD-карты (т.е./Storage/A5F9-15F4), но он не соответствовал регулярному выражению, поэтому он не возвращался. Я не получаю механизм именования каталогов, за которым следует Samsung. Почему они отклоняются от стандартов (т.е. Extsdcard) и придумывают что-то действительно подозрительное, как в моем случае (т.е./Storage/A5F9-15F4). Есть что-то, чего я не вижу? В любом случае, следующие изменения в регулярном выражении решения Gnathonic помогли мне получить действительный каталог sdcard:

final HashSet<String> out = new HashSet<String>();
        String reg = "(?i).*(vold|media_rw).*(sdcard|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;

Я не уверен, что это действительное решение, и если он даст результаты для других планшетов Samsung, но на данный момент он исправил мою проблему. Ниже приведен еще один способ получения сменного SD-карты в Android (v6.0). Я тестировал метод с android marshmallow, и он работает. Подход, используемый в нем, очень простой и, безусловно, будет работать и для других версий, но тестирование является обязательным. Некоторое понимание этого будет полезно:

public static String getSDCardDirPathForAndroidMarshmallow() {

    File rootDir = null;

    try {
        // Getting external storage directory file
        File innerDir = Environment.getExternalStorageDirectory();

        // Temporarily saving retrieved external storage directory as root
        // directory
        rootDir = innerDir;

        // Splitting path for external storage directory to get its root
        // directory

        String externalStorageDirPath = innerDir.getAbsolutePath();

        if (externalStorageDirPath != null
                && externalStorageDirPath.length() > 1
                && externalStorageDirPath.startsWith("/")) {

            externalStorageDirPath = externalStorageDirPath.substring(1,
                    externalStorageDirPath.length());
        }

        if (externalStorageDirPath != null
                && externalStorageDirPath.endsWith("/")) {

            externalStorageDirPath = externalStorageDirPath.substring(0,
                    externalStorageDirPath.length() - 1);
        }

        String[] pathElements = externalStorageDirPath.split("/");

        for (int i = 0; i < pathElements.length - 1; i++) {

            rootDir = rootDir.getParentFile();
        }

        File[] files = rootDir.listFiles();

        for (File file : files) {
            if (file.exists() && file.compareTo(innerDir) != 0) {

                // Try-catch is implemented to prevent from any IO exception
                try {

                    if (Environment.isExternalStorageRemovable(file)) {
                        return file.getAbsolutePath();

                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }

            }
        }
    } catch (Exception ex) {
        ex.printStackTrace();
    }
    return null;
}

Просьба поделиться, если у вас есть другой подход к решению этой проблемы. Благодаря

Ответ 24

//manifest file outside the application tag
//please give permission write this 
//<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
        File file = new File("/mnt");
        String[] fileNameList = file.list(); //file names list inside the mnr folder
        String all_names = ""; //for the log information
        String foundedFullNameOfExtCard = ""; // full name of ext card will come here
        boolean isExtCardFounded = false;
        for (String name : fileNameList) {
            if (!isExtCardFounded) {
                isExtCardFounded = name.contains("ext");
                foundedFullNameOfExtCard = name;
            }
            all_names += name + "\n"; // for log
        }
        Log.d("dialog", all_names + foundedFullNameOfExtCard);

Ответ 25

В Galaxy S3 Android 4.3 путь, который я использую, ./storage/extSdCard/Card/, и он выполняет эту работу. Надеюсь, это поможет,

Ответ 26

Следующие шаги работали для меня. Вам просто нужно написать следующие строки:

String sdf = new String(Environment.getExternalStorageDirectory().getName());
String sddir = new String(Environment.getExternalStorageDirectory().getPath().replace(sdf,""));

В первой строке указывается имя sd-каталога, и вам просто нужно использовать его в методе replace для второй строки. Вторая строка будет содержать путь для внутреннего и съемного sd (/storage/in my case). Мне просто нужен этот путь для моего приложения, но вы можете пойти дальше, если вам это нужно.