写入不同的SD卡时出错

时间:2014-09-14 17:41:50

标签: android sd-card fileoutputstream

我正在编写一种方法将文件写入设备上的任何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

出了什么问题?我该如何解决?

1 个答案:

答案 0 :(得分:1)

  

出了什么问题?

您似乎认为Environment.getExternalStorageDirectory()与SD卡有关。从SDK的角度来看,该方法返回external storage的根,它不是removable storage(也不是internal storage

但是,更重要的是,未记录和不支持意味着脚本小子用于访问可移动存储的各种人 - 例如您正在尝试的内容 - 不再适用于Android 4.4。

  

我需要访问设备上的所有SD卡

从Android 4.4开始就不再可能了,并且在任何版本的Android上都不支持。