三星 Galaxy S3有一个外部 SD 卡插槽,可安装到/mnt/extSdCard
.
我怎样才能通过类似的方式获得这条路径Environment.getExternalStorageDirectory()
?
这将返回mnt/sdcard
,我找不到外部 SD 卡的 API。(或某些平板电脑上的可移动 USB 存储设备。)
三星 Galaxy S3有一个外部 SD 卡插槽,可安装到/mnt/extSdCard
.
我怎样才能通过类似的方式获得这条路径Environment.getExternalStorageDirectory()
?
这将返回mnt/sdcard
,我找不到外部 SD 卡的 API。(或某些平板电脑上的可移动 USB 存储设备。)
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;
}
原始方法经过测试和使用
我不确定它们在测试时使用的是哪个 android 版本。
我已经测试了我的修改版本
以及一些使用 sdcard 作为主存储的单一存储设备
除了 Incredible 之外,所有这些设备都只返回了它们的可移动存储。我可能应该做一些额外的检查,但这至少比我迄今为止找到的任何解决方案都要好一些。
我找到了更可靠的方法来获取系统中所有 SD-CARD 的路径。这适用于所有 Android 版本并返回所有存储的路径(包括模拟)。
在我所有的设备上都能正常工作。
PS:基于环境类的源代码。
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()]);
}
我想使用你需要使用的外部 sdcard:
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?
}
我一直在使用Dmitriy Lozenko的解决方案,直到我检查了Asus Zenfone2、Marshmallow 6.0.1并且该解决方案不起作用。获取EMULATED_STORAGE_TARGET时解决方案失败,特别是针对 microSD 路径,即:/storage/F99C-10F4/。我编辑了代码以直接从模拟的应用程序路径获取模拟的根路径,context.getExternalFilesDirs(null);
并添加了更多已知的特定于手机型号的物理路径。
为了让我们的生活更轻松,我在这里做了一个图书馆。您可以通过 gradle、maven、sbt 和 leiningen 构建系统使用它。
如果你喜欢老式的方式,你也可以直接从这里复制粘贴文件,但如果不手动检查,你将不知道以后是否有更新。
如果您有任何问题或建议,请告诉我
为了检索所有外部存储(无论是SD 卡还是内部不可移动存储),您可以使用以下代码:
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");
}
}
}
}
或者,您可以使用System.getenv("EXTERNAL_STORAGE")检索主外部存储目录(例如"/storage/sdcard0")和System.getenv("SECONDARY_STORAGE")检索所有辅助目录的列表(例如" /storage/extSdCard:/storage/UsbDriveA:/storage/UsbDriveB")。请记住,同样在这种情况下,您可能希望过滤二级目录列表以排除 USB 驱动器。
在任何情况下,请注意使用硬编码路径总是一种不好的方法(特别是当每个制造商都可以随意更改它时)。
好消息!在 KitKat 中,现在有一个公共 API 用于与这些辅助共享存储设备进行交互。
新的Context.getExternalFilesDirs()
和Context.getExternalCacheDirs()
方法可以返回多个路径,包括主设备和辅助设备。然后,您可以遍历它们并检查Environment.getStorageState()
并File.getFreeSpace()
确定存储文件的最佳位置。ContextCompat
这些方法在 support-v4 库中也可用。
另请注意,如果您只对使用返回的目录感兴趣,则Context
不再需要READ_
orWRITE_EXTERNAL_STORAGE
权限。展望未来,您将始终拥有对这些目录的读/写访问权限,而无需其他权限。
应用程序还可以通过终止其权限请求来继续在旧设备上工作,如下所示:
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="18" />
我做了以下操作来访问所有外部 sd 卡。
和:
File primaryExtSd=Environment.getExternalStorageDirectory();
您将获得主要外部 SD 的路径然后使用:
File parentDir=new File(primaryExtSd.getParent());
你得到主外部存储的父目录,它也是所有外部 sd 的父目录。现在,您可以列出所有存储并选择您想要的存储。
希望它有用。
找到了一种从 Android N 开始更正式的新方法(如果以前,你可以尝试我上面写的),特别是从 Android R,使用 StorageManager(基于我在这里写的解决方案):
class MainActivity : AppCompatActivity() {
@RequiresApi(Build.VERSION_CODES.N)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
getSdCardPaths(this, true)?.forEach { volumePath ->
Log.d("AppLog", "volumePath:$volumePath")
}
}
/**
* 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
*/
fun getSdCardPaths(context: Context, includePrimaryExternalStorage: Boolean): List<String>? {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
val storageManager = context.getSystemService(Context.STORAGE_SERVICE) as StorageManager
val storageVolumes = storageManager.storageVolumes
if (!storageVolumes.isNullOrEmpty()) {
val primaryVolume = storageManager.primaryStorageVolume
val result = ArrayList<String>(storageVolumes.size)
for (storageVolume in storageVolumes) {
val volumePath = getVolumePath(storageVolume) ?: continue
if (storageVolume.uuid == primaryVolume.uuid || storageVolume.isPrimary) {
if (includePrimaryExternalStorage)
result.add(volumePath)
continue
}
result.add(volumePath)
}
return if (result.isEmpty()) null else result
}
}
val externalCacheDirs = ContextCompat.getExternalCacheDirs(context)
if (externalCacheDirs.isEmpty())
return null
if (externalCacheDirs.size == 1) {
if (externalCacheDirs[0] == null)
return null
val storageState = EnvironmentCompat.getStorageState(externalCacheDirs[0])
if (Environment.MEDIA_MOUNTED != storageState)
return null
if (!includePrimaryExternalStorage && Environment.isExternalStorageEmulated())
return null
}
val result = ArrayList<String>()
if (externalCacheDirs[0] != null && (includePrimaryExternalStorage || externalCacheDirs.size == 1))
result.add(getRootOfInnerSdCardFolder(context, externalCacheDirs[0]))
for (i in 1 until externalCacheDirs.size) {
val file = externalCacheDirs[i] ?: continue
val storageState = EnvironmentCompat.getStorageState(file)
if (Environment.MEDIA_MOUNTED == storageState)
result.add(getRootOfInnerSdCardFolder(context, externalCacheDirs[i]))
}
return if (result.isEmpty()) null else result
}
fun getRootOfInnerSdCardFolder(context: Context, inputFile: File): String {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
val storageManager = context.getSystemService(Context.STORAGE_SERVICE) as StorageManager
storageManager.getStorageVolume(inputFile)?.let {
val result = getVolumePath(it)
if (result != null)
return result
}
}
var file: File = inputFile
val totalSpace = file.totalSpace
while (true) {
val parentFile = file.parentFile
if (parentFile == null || parentFile.totalSpace != totalSpace || !parentFile.canRead())
return file.absolutePath
file = parentFile
}
}
@RequiresApi(Build.VERSION_CODES.N)
fun getVolumePath(storageVolume: StorageVolume): String? {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R)
return storageVolume.directory?.absolutePath
try {
val storageVolumeClazz = StorageVolume::class.java
val getPath = storageVolumeClazz.getMethod("getPath")
return getPath.invoke(storageVolume) as String
} catch (e: Exception) {
e.printStackTrace()
}
return null
}
}
感谢你们提供的线索,尤其是@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 不存在,我将使用它,您可能需要更改它。
参考我的代码,希望对你有帮助:
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);
System.getenv("SECONDARY_STORAGE")
该解决方案(由该问题的其他答案组装而成)处理了对 Marshmallow 没有用的事实(如@ono 所述) 。
测试和工作:
三星 Galaxy Tab A(Android 6.0.1 - 库存)
/**
* 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;
}
实际上,在某些设备中,外部 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);
}
是的。不同的制造商使用不同的 SD 卡名称,如三星 Tab 3 它的 extsd,而其他三星设备使用不同的 SD 卡,不同的制造商使用不同的名称。
我和你有同样的要求。所以我从我的项目中为您创建了一个示例示例转到此链接Android 目录选择器示例,该示例使用 android-dirchooser 库。此示例检测 SD 卡并列出所有子文件夹,它还检测设备是否有多个 SD 卡。
部分代码如下所示完整示例转到链接Android 目录选择器
/**
* 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);
}
}
});
在某些设备(例如三星 Galaxy sII)上,内部存储卡可能位于 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;
}
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);
}
System.getenv("SECONDARY_STORAGE")
为棉花糖返回 null。这是另一种查找所有外部目录的方法。您可以检查它是否可移动,这决定了内部/外部
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
File[] externalCacheDirs = context.getExternalCacheDirs();
for (File file : externalCacheDirs) {
if (Environment.isExternalStorageRemovable(file)) {
// It's a removable storage
}
}
}
我相信这段代码肯定会解决你的问题......这对我来说很好......\
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();
}
要访问我的SD 卡中的文件,在我的 HTC One X (Android) 上,我使用以下路径:
file:///storage/sdcard0/folder/filename.jpg
注意三个“/”!
String path = Environment.getExternalStorageDirectory()
+ File.separator + Environment.DIRECTORY_PICTURES;
File dir = new File(path);
您可以使用类似的东西 - Context.getExternalCacheDirs() 或 Context.getExternalFilesDirs() 或 Context.getObbDirs()。它们在应用程序可以存储其文件的所有外部存储设备中提供应用程序特定的目录。
所以像这样的东西 - Context.getExternalCacheDirs()[i].getParentFile().getParentFile().getParentFile().getParent() 可以获得外部存储设备的根路径。
我知道这些命令用于不同的目的,但其他答案对我不起作用。
这个链接给了我很好的指示 - https://possiblemobile.com/2014/03/android-external-storage/
String secStore = System.getenv("SECONDARY_STORAGE");
File externalsdpath = new File(secStore);
这将获得外部 sd 二级存储的路径。
我在我的三星 Galaxy Tab S2(型号:T819Y)上尝试了Dmitriy Lozenko和Gnathonic提供的解决方案,但没有一个帮助我检索到外部 SD 卡目录的路径。命令执行包含外部 SD 卡目录(即 /Storage/A5F9-15F4)所需的路径,但它与正则表达式不匹配,因此未返回。我没有得到三星遵循的目录命名机制。为什么他们偏离标准(即 extsdcard)并想出像我的情况一样非常可疑的东西(即 /Storage/A5F9-15F4)。有什么我想念的吗?无论如何,随着Gnathonic正则表达式的变化mount
解决方案帮助我获得了有效的 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;
我不确定这是否是一个有效的解决方案,以及它是否会为其他三星平板电脑提供结果,但它现在已经解决了我的问题。以下是在 Android (v6.0) 中检索可移动 SD 卡路径的另一种方法。我已经用 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;
}
如果您有任何其他方法来处理此问题,请分享。谢谢
//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);
这不是真的。即使未挂载 SD 卡,/mnt/sdcard/external_sd 也可以存在。当您在未安装时尝试写入 /mnt/sdcard/external_sd 时,您的应用程序将崩溃。
您需要检查是否首先使用以下方法安装了 SD 卡:
boolean isSDPresent = Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
在 Galaxy S3 Android 4.3 上,我使用的路径是./storage/extSdCard/Card/,它可以完成这项工作。希望能帮助到你,
以下步骤对我有用。你只需要写这行:
String sdf = new String(Environment.getExternalStorageDirectory().getName());
String sddir = new String(Environment.getExternalStorageDirectory().getPath().replace(sdf,""));
第一行将给出 sd 目录的名称,您只需在第二个字符串的 replace 方法中使用它。第二个字符串将包含内部和可移动sd(/storage/ 在我的情况下)的路径。我的应用程序只需要这条路径,但如果需要,您可以走得更远。