无法写入SD卡

时间:2014-04-24 20:47:14

标签: android

我的应用程序允许用户拍照,我希望该图片存储在应用程序的外部文件目录(getExternalFilesDir(null))中。除了拨打renameTo()之外,这一切都有效,此通话返回false,我不知道原因。

src文件是:

/storage/extSdCard/DCIM/Camera/20140424_154458.jpg

目的地文件是:

/storage/emulated/0/Android/data/com.myapp.myapp/files/20140424_154458.jpg

我也指定了WRITE_EXTERNAL_STORAGE权限。

@Override
public boolean onOptionsItemSelected(MenuItem item)
{
    if (item.getItemId() == R.id.action_take_picture)
    {
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        startActivityForResult(intent, TAKE_PICTURE_REQUEST_CODE);
        return true;
    }
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
    if (requestCode == TAKE_PICTURE_REQUEST_CODE && resultCode == RESULT_OK)
    {
        File dest = new File(
            getExternalFilesDir(null),
            new SimpleDateFormat("yyyyMMdd_hhmmss", Locale.getDefault()).format(new Date()) + ".jpg");

        File src = new File(convertMediaUriToPath(data.getData()));
        if (src.renameTo(dest)) // Always returns false
        {
            mAdapter.add(dest);
            mAdapter.notifyDataSetChanged();
        }
    }
}

private String convertMediaUriToPath(Uri uri)
{
    String[] proj = {MediaStore.Images.Media.DATA};
    Cursor cursor = getContentResolver().query(uri, proj, null, null, null);
    int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
    cursor.moveToFirst();
    String path = cursor.getString(column_index);
    cursor.close();

    return path;
}

3 个答案:

答案 0 :(得分:3)

我以前遇到过这个问题 - 遗憾的是,您不能使用renameTo在不同的挂载点(例如,内部和外部存储)之间移动文件和/或目录。考虑使用不同的移动文件方式,例如此处概述的方法:

http://www.mkyong.com/java/how-to-copy-directory-in-java/

public static void copyFolder(File src, File dest) throws IOException{

    if(src.isDirectory()){

        //if directory not exists, create it
        if(!dest.exists()){
           dest.mkdir();
           System.out.println("Directory copied from " 
                          + src + "  to " + dest);
        }

        //list all the directory contents
        String files[] = src.list();

        for (String file : files) {
           //construct the src and dest file structure
           File srcFile = new File(src, file);
           File destFile = new File(dest, file);
           //recursive copy
           copyFolder(srcFile,destFile);
        }

    }else{
        //if file, then copy it
        //Use bytes stream to support all file types
        InputStream in = new FileInputStream(src);
            OutputStream out = new FileOutputStream(dest); 

            byte[] buffer = new byte[1024];

            int length;
            //copy the file content in bytes 
            while ((length = in.read(buffer)) > 0){
               out.write(buffer, 0, length);
            }

            in.close();
            out.close();
            System.out.println("File copied from " + src + " to " + dest);
    }
}

答案 1 :(得分:1)

问题在于方法renameTorenameTo不会创建子目录,

原因是当前的File API在Java中实现得不是很好。在当前不存在的文件API中有许多功能,例如移动,复制和检索文件元数据。

我认为没有人能够回答为什么API按原样编写。可能是一个糟糕的初稿,由于向后兼容性问题而上线并且无法更改。

这些问题已在Java 7中得到解决。已经创建了一个全新的API来处理文件java.nio.file.Files

要解决此问题,请尝试获取目标文件的目录路径 e.g /storage/emulated/0/Android/data/com.myapp.myapp/files/20140424_154458.jpg

目的地目录是 /storage/emulated/0/Android/data/com.myapp.myapp/files/

使用mkdirs(),它将为您创建所有子目录

答案 2 :(得分:0)

如果要添加文件或文件夹或将应用程序移动到SD卡中,请执行以下操作:

步骤进行:

1)使用文本或编程编辑器打开Android应用程序的源代码文件。 2)浏览到源代码中您希望调用将文件写入设备外部存储器的功能的位置。 3)插入这一行代码以检查SD卡:

File sdCard = Environment.getExternalStorageDirectory();

4)插入这些代码行来设置目录和文件名:

File dir = new File (sdcard.getAbsolutePath() + "/folder1/folder2");
dir.mkdirs();
File file = new File(dir, "example_file");

// The mkdirs function will create the directory folder for you, use it only you want to create a new one.

5)替换" / folder1 / folder2"在上面的代码中,您打算保存文件的实际路径。这应该是您通常保存应用程序文件的位置。另外,更改" example_file"值为您要使用的实际文件名。

6)插入以下代码行将文件输出到SD卡:

FileOutputStream f = new FileOutputStream(file);
Finally step 7:

保存文件,然后编译并使用Android模拟器软件或设备测试应用程序。

这会有效!!! ; - )