I'm developing a File Manager app. I want show to the user the internal storage and the sdcard storage if it exists. For internal storage I use Environment.getExternalStorageDirectory().getPath()
. How can I get the SD storage?
可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
回答1:
not sure this solution fits a File Manager but after many years trying to get the right code, this is my most recent one:
/**
* Returns 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 standard way to get it.
*
* @return paths to all available SD-Cards in the system (include emulated)
*/
public static String[] getStorageDirectories(Context pContext)
{
// Final set of paths
final Set<String> rv = new HashSet<>();
//Get primary & secondary external device storage (internal storage & micro SDCARD slot...)
File[] listExternalDirs = ContextCompat.getExternalFilesDirs(pContext, null);
for(int i=0;i<listExternalDirs.length;i++){
if(listExternalDirs[i] != null) {
String path = listExternalDirs[i].getAbsolutePath();
int indexMountRoot = path.indexOf("/Android/data/");
if(indexMountRoot >= 0 && indexMountRoot <= path.length()){
//Get the root path for the external directory
rv.add(path.substring(0, indexMountRoot));
}
}
}
return rv.toArray(new String[rv.size()]);
}
回答2:
If you worked on only Android 4.0+.These answers here will help you:
how-can-i-get-external-sd-card-path-for-android-4-0
Some code example from the answers:
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;
}
Another answer here.
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()]);
}
The third answer is:
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");
}
}
}
}
回答3:
Similar to code above but without harcoded "/Android/data"
public List<File> getAllStorageLocations() {
List<File> storageLocations = new ArrayList<>();
File storageDir = Environment.getExternalStorageDirectory();
String storagePath = storageDir.getAbsolutePath();
File[] extFileDirs = getContext().getExternalFilesDirs(null);
String suffixToStrip = null;
for (File nextFile : extFileDirs) {
String nextPath = nextFile.getAbsolutePath();
if (nextPath.startsWith(storagePath)) {
suffixToStrip = nextPath.substring(storagePath.length());
break;
}
}
if (suffixToStrip != null) {
for (File nextFile : extFileDirs) {
String nextPath = nextFile.getAbsolutePath();
int stripIndex = nextPath.lastIndexOf(suffixToStrip);
if (stripIndex > -1) {
File path = new File(nextPath.substring(0, stripIndex));
storageLocations.add(path);
}
}
}
if (storageLocations.size() == 0) {
storageLocations.add(storageDir);
}
return storageLocations;
}
回答4:
Try this, iterate from root folder.
File rootFolder = new File("/");
boolean isSdcardRemovable = false;
String path = null;
loop:
for(int i=0; i<rootFolder.listFiles().length; i++) {
if(rootFolder.listFiles()[i].listFiles() != null &&
!rootFolder.listFiles()[i].toString().contains("system") &&
!rootFolder.listFiles()[i].toString().contains("etc") &&
!rootFolder.listFiles()[i].toString().contains("dev") ) {
File dataDir = new File(Environment.getDataDirectory().getAbsolutePath());
long dataDirSize = dataDir.getFreeSpace()/(1000*1000);
long folderSize = rootFolder.listFiles()[i].getFreeSpace()/(1000*1000);
if(dataDirSize == folderSize || (dataDirSize > folderSize &&
folderSize > (dataDirSize-80))) {
System.err.println("INTERNAL1 "+rootFolder.listFiles()[i]);
System.err.println(dataDirSize);
System.err.println(folderSize);
}
else {
File rootSubFolder1 = new File(rootFolder.listFiles()[i].getAbsolutePath());
if(rootSubFolder1.listFiles() != null) {
for(int j=0; j<rootSubFolder1.listFiles().length; j++) {
if(rootSubFolder1.listFiles()[j].getTotalSpace() != 0 &&
rootSubFolder1.listFiles()[j].getFreeSpace() != 0 &&
rootSubFolder1.listFiles()[j].listFiles() != null) {
Log.i(TAG, "" + rootSubFolder1.listFiles()[j]);
if(rootSubFolder1.listFiles()[j].toString().contains("sdcard") ||
rootSubFolder1.listFiles()[j].toString().contains("storage") ||
rootSubFolder1.listFiles()[j].toString().contains("mnt")) {
folderSize = rootSubFolder1.listFiles()[j].getFreeSpace()/(1000*1000);
if(dataDirSize == folderSize || (dataDirSize > folderSize &&
folderSize > (dataDirSize-80))) {
System.err.println("INTERNAL2 " + rootSubFolder1.listFiles()[j]);
System.err.println(dataDirSize);
System.err.println(folderSize);
}
else {
int pos = rootSubFolder1.listFiles()[j].getAbsolutePath().lastIndexOf('/');
String str = rootSubFolder1.listFiles()[j].getAbsolutePath().substring(pos+1);
if(str.matches("(sd|ext|3039|m_external_sd).*")) {
isSdcardRemovable = true;
System.err.println("EXTERNAL "+rootSubFolder1.listFiles()[j]);
System.err.println(dataDirSize);
System.err.println(folderSize);
path = rootSubFolder1.listFiles()[j].getAbsolutePath()+"/";
break loop;
}
}
}
}
}
}
}
}
}
if(isSdcardRemovable) {
if(path != null) {
getMemoryDetails(path);
finish();
}
else {
saveResult("fail", "External memory not found.");
Log.e(TAG, "External memory not found.");
finish();
}
} else {
saveResult("fail", "External memory not available.");
Log.e(TAG, "External memory not available.");
finish();
}