Внешний путь к файлу SDCard для Android
Правда ли, что путь к внешней SDCard на устройствах Android всегда "/storage/extSdCard" ? Если нет, сколько вариантов есть?
Мне нужно для моего приложения проверить наличие внешней SDCard.
Я использую Titanium, у него есть метод Titanium.Filesystem.isExternalStoragePresent()
но он всегда возвращает истину, даже внешняя SDCard не смонтирована.
Я думаю, что он обнаруживает SDCard в локальном хранилище, таким образом, возвращает true. Но я действительно хочу определить, установлена ли физическая SDCard или нет.
Могу ли я это сделать, обнаружив существование файла "/storage/extSdCard" самостоятельно?
Спасибо.
Ответы
Ответ 1
Правда ли, что путь к внешней SDCard на устройствах Android всегда "/storage/extSdCard"? Если нет, сколько вариантов есть?
К сожалению, путь к внешнему хранилищу не всегда одинаковый в зависимости от производителя. Использование Environment.getExternalStorageDirectory()
вернет вам нормальный путь для SD-карты, которая равна mnt/sdcard/
. Например, для устройств Samsung путь к SD-карте находится под mnt/extSdCard/
или под mnt/external_sd/
.
Таким образом, одним из способов продолжения было бы проверить наличие внешнего каталога в соответствии с путем, используемым каждым производителем. Что-то вроде этого:
mExternalDirectory = Environment.getExternalStorageDirectory()
.getAbsolutePath();
if (android.os.Build.DEVICE.contains("samsung")
|| android.os.Build.MANUFACTURER.contains("samsung")) {
File f = new File(Environment.getExternalStorageDirectory()
.getParent() + "/extSdCard" + "/myDirectory");
if (f.exists() && f.isDirectory()) {
mExternalDirectory = Environment.getExternalStorageDirectory()
.getParent() + "/extSdCard";
} else {
f = new File(Environment.getExternalStorageDirectory()
.getAbsolutePath() + "/external_sd" + "/myDirectory");
if (f.exists() && f.isDirectory()) {
mExternalDirectory = Environment
.getExternalStorageDirectory().getAbsolutePath()
+ "/external_sd";
}
}
}
Но я действительно хочу определить, установлена ли физическая SDCard или нет.
Я еще не пробовал код, но подход Дмитрия Лозенко в этом ответе гораздо интереснее. Его метод возвращает путь для всех смонтированных SD-карт на системе независимо от производителя.
Ответ 2
Надеюсь, это будет полезно для вас:)
import android.os.Environment;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
public class MemoryStorage {
private MemoryStorage() {}
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 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;
}
}
Ответ 3
Вот как я, наконец, получил sdcard путь, используя:
public String getExternalStoragePath() {
String internalPath = Environment.getExternalStorageDirectory().getAbsolutePath();
String[] paths = internalPath.split("/");
String parentPath = "/";
for (String s : paths) {
if (s.trim().length() > 0) {
parentPath = parentPath.concat(s);
break;
}
}
File parent = new File(parentPath);
if (parent.exists()) {
File[] files = parent.listFiles();
for (File file : files) {
String filePath = file.getAbsolutePath();
Log.d(TAG, filePath);
if (filePath.equals(internalPath)) {
continue;
} else if (filePath.toLowerCase().contains("sdcard")) {
return filePath;
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
try {
if (Environment.isExternalStorageRemovable(file)) {
return filePath;
}
} catch (RuntimeException e) {
Log.e(TAG, "RuntimeException: " + e);
}
}
}
}
return null;
}
Ответ 4
У меня есть решение по этому поводу через 4 дня. Обратите внимание на следующие моменты, указывая путь к классу File в Android (Java):
- Использовать путь для внутреннего хранилища String
path="/storage/sdcard0/myfile.txt";
- использовать путь для внешнего хранилища
path="/storage/sdcard1/myfile.txt";
- укажите разрешения в файле манифеста.
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
- Сначала проверьте длину файла для подтверждения.
- Проверить пути в ES File Explorer относительно sdcard0 и sdcard1
это же или иначе...
например:.
File file = new File(path);
long = file.length();//in Bytes
Ответ 5
Я что-то понял. По крайней мере, для моего эмулятора Android у меня был SD Card Path, например '/storage/???? -???? ', где каждая ? является заглавной буквой или цифрой.
Итак, если каталог /storage/ имеет каталог, который доступен для чтения и который не является внутренним хранилищем, должен быть SD-картой.
Мой код работал на моем эмуляторе Android!
String removableStoragePath;
File fileList[] = new File("/storage/").listFiles();
for (File file : fileList)
{ if(!file.getAbsolutePath().equalsIgnoreCase(Environment.getExternalStorageDirectory().getAbsolutePath()) && file.isDirectory() && file.canRead())
removableStoragePath = file.getAbsolutePath(); }
//If there is an SD Card, removableStoragePath will have it path. If there isn't it will be an empty string.
Если есть SD-карта, съемныйStoragePath будет иметь его путь. Если нет, это будет пустая строка.