我正在编写一种方法将文件写入设备上的任何SD卡。
例如,我获得三星Galaxy S4的2个SD卡路径:/ storage / emulated / 0是内部SD卡的路径,等于Environment.getExternalStorageDirectory()
和/ storage / extSdCard
这里是获取可用SD卡 - 根路径列表的方法:
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()]);
}
所以,这个方法在我的情况下返回2个路径:/ storage / emulated / 0和/ storage / extSdCard
然后我尝试写这个文件:
public static boolean writeExternal(InputStream source, String filePath) {
Log.d("MyLog", "dest="+filePath);
// собственно запись на флешку
File dest = new File(filePath);
FileOutputStream writer = null;
try {
if (!dest.exists()) {
Log.d("MyLog","creates");
dest.getParentFile().mkdirs();
dest.createNewFile();
}
writer = new FileOutputStream(dest);
writeFromInputToOutput(source, writer);
Log.d("MyLog","writes a file "+filePath);
return true;
}
catch (IOException e) {
e.printStackTrace();
Log.d("MyLog","Error");
return false;
}
finally {
Log.d("MyLog","file written");
close(writer);
}
}
现在当我将文件写入第一个目录/ storage / emulated / 0时 - 文件创建正常。 但第二个目录 - / storage / extSdCard给了我一个错误。 这是我的堆栈跟踪并记录路径以检查它(它是第一行):
09-15 01:32:24.124: D/MyLog(26216): dest=/storage/extSdCard/Molitvoslovaudio/morning.mp3
09-15 01:32:24.124: D/MyLog(26216): creates
09-15 01:32:24.124: W/System.err(26216): java.io.IOException: open failed: ENOENT (No such file or directory)
09-15 01:32:24.139: W/System.err(26216): at java.io.File.createNewFile(File.java:946)
09-15 01:32:24.139: W/System.err(26216): at ru.eyescream.prayer.FileMgr.writeExternal(FileMgr.java:156)
09-15 01:32:24.139: W/System.err(26216): at ru.eyescream.prayer.Downloader$Downloading.onPostExecute(Downloader.java:183)
09-15 01:32:24.139: W/System.err(26216): at ru.eyescream.prayer.Downloader$Downloading.onPostExecute(Downloader.java:1)
09-15 01:32:24.139: W/System.err(26216): at android.os.AsyncTask.finish(AsyncTask.java:632)
09-15 01:32:24.139: W/System.err(26216): at android.os.AsyncTask.access$600(AsyncTask.java:177)
09-15 01:32:24.139: W/System.err(26216): at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:645)
09-15 01:32:24.139: W/System.err(26216): at android.os.Handler.dispatchMessage(Handler.java:102)
09-15 01:32:24.139: W/System.err(26216): at android.os.Looper.loop(Looper.java:157)
09-15 01:32:24.139: W/System.err(26216): at android.app.ActivityThread.main(ActivityThread.java:5356)
09-15 01:32:24.139: W/System.err(26216): at java.lang.reflect.Method.invokeNative(Native Method)
09-15 01:32:24.139: W/System.err(26216): at java.lang.reflect.Method.invoke(Method.java:515)
09-15 01:32:24.139: W/System.err(26216): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1265)
09-15 01:32:24.139: W/System.err(26216): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1081)
09-15 01:32:24.139: W/System.err(26216): at dalvik.system.NativeStart.main(Native Method)
09-15 01:32:24.139: W/System.err(26216): Caused by: libcore.io.ErrnoException: open failed: ENOENT (No such file or directory)
09-15 01:32:24.139: W/System.err(26216): at libcore.io.Posix.open(Native Method)
09-15 01:32:24.139: W/System.err(26216): at libcore.io.BlockGuardOs.open(BlockGuardOs.java:110)
09-15 01:32:24.139: W/System.err(26216): at java.io.File.createNewFile(File.java:939)
09-15 01:32:24.139: W/System.err(26216): ... 14 more
09-15 01:32:24.139: D/MyLog(26216): Error
出了什么问题?我该如何解决?
答案 0 :(得分:1)
出了什么问题?
您似乎认为Environment.getExternalStorageDirectory()
与SD卡有关。从SDK的角度来看,该方法返回external storage的根,它不是removable storage(也不是internal storage。
但是,更重要的是,未记录和不支持意味着脚本小子用于访问可移动存储的各种人 - 例如您正在尝试的内容 - 不再适用于Android 4.4。
我需要访问设备上的所有SD卡
从Android 4.4开始就不再可能了,并且在任何版本的Android上都不支持。