Как я могу получить внешний путь 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). Мне просто нужен этот путь для моего приложения, но вы можете пойти дальше, если вам это нужно.