Android无法在SD卡上写入和删除操作

时间:2018-08-23 08:41:15

标签: java android permissions file-permissions storage-access-framework

我现在正在使用ImageCompressor应用程序。

我需要deletewrite(更新)图像文件。在内部存储中,效果很好,但** SD卡无法让我访问“删除和写入”文件。

我的应用程序如何在SD卡上执行writedelete操作(可移动存储)?

没有这个,我已经完成了整个项目,所以我必须找到一种方法。

更新:

我已经在研究和讨论此问题。并且了解我必须使用storage access framework,但是我对SAF还是陌生的。

我使用了来压缩需要文件而不是Uri 的照片。为此,我Uri -> File并使用Intent.ACTION_OPEN_DOCUMENT并从可移动存储中选择图像。

  

但是对于可移动存储,我无法从uri中找到Image Real Path。

我不知道这是正确的方法。如果在SAF中可以通过使用uri压缩图像的任何方式,请告诉我。或如何从可移动存储照片的uri获取图像的真实路径

更新代码SAF:

//  -----------  Intent  -------------
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*");

//  ------------  On Activity Result  --------------
Uri uri = data.getData();
try {
    ParcelFileDescriptor fileDescriptor = getContentResolver().openFileDescriptor(uri, "w");
    FileOutputStream fos = new FileOutputStream(fileDescriptor.getFileDescriptor());

    FileInputStream fis = new FileInputStream(getImageFilePath(uri));

    FileChannel source = fis.getChannel();
    FileChannel destination = fos.getChannel();
    destination.transferFrom(source, 0, source.size());

    fis.close();
    fos.close();
    fileDescriptor.close();
    Toast.makeText(this, "File save successfully.", Toast.LENGTH_SHORT).show();
}

从Uri到文件路径,我从媒体应用(如Gallary,Photos)中选择图像,但是从sd卡中选择了什么,而不是MediaStore.Images.Media.DATA,我不知道。代码:

private File getImageFilePath(Uri uri) throws IOException {
    String image_id = null, imagePath = null;

    Cursor cursor = getContentResolver().query(uri, null, null, null, null);
    if (cursor != null) {
        cursor.moveToFirst();
        image_id = cursor.getString(0);
        image_id = image_id.substring(image_id.lastIndexOf(":") + 1);
        cursor.close();
    }
    cursor = getContentResolver().query(android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI, null, MediaStore.Images.Media._ID + " = ? ", new String[]{image_id}, null);
    if (cursor!=null) {
        cursor.moveToFirst();
        imagePath = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
        cursor.close();
    }

    File file = new File(imagePath);
    return new Compressor(this).setQuality(50).compressToFile(file);
}

3 个答案:

答案 0 :(得分:4)

如果您使用File和FileOutputStream类,则只能在现代Android设备上写入可移动SD卡。

如果幸运的话,使用getExternalFilesDirs()的设备将返回卡上仍可写入的应用程序特定目录作为第二项。

其余部分,请使用存储访问框架。

首先让用户选择带有Intent.ACTION_OPEN_DOCUMENT_TREE的sd卡或带有Intent.ACTION_OPEN_DOCUMENT的文件。

答案 1 :(得分:1)

我挖了一个我的旧Android应用程序,并找到了它:

此方法将sdcard uri的根转换为File路径。

public File getRootPath(Context context, Uri sdcardRootUri)
{
    List<String> pathSegments =  sdcardRootUri.getPathSegments();
    String[] tokens = pathSegments.get(pathSegments.size()-1).split(":");
    for (File f : ContextCompat.getExternalFilesDirs(context, null))
    {
        String path = f.getAbsolutePath().substring(0, f.getAbsolutePath().indexOf("/Android/"));
        if (path.contains(tokens[0]))
        {
            return new File(path);
        }
    }
    return null;
}

为了检索sdcard根的uri,我使用了它:

Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
startActivityForResult(intent, SDCARD_ROOT_CODE);

然后用户将选择sdcard的根,然后,我像这样处理结果:

protected void onActivityResult(int requestCode, int resultCode, Intent data) 
{
    if (resultCode == RESULT_OK && requestCode == SDCARD_ROOT_CODE)
    {
        // Persist access permissions
        Uri sdcdardRootUri = data.getData();
        grantUriPermission(getPackageName(), sdcdardRootUri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
        final int takeFlags = data.getFlags() & (Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
        getContentResolver().takePersistableUriPermission(sdcdardRootUri, takeFlags);

        // Do whatever you want with sdcdardRootUri
    }
}

我希望这是您想要的。这样,您可以读取/写入/删除sdcard上想要的任何文件。

答案 2 :(得分:-1)

您可以尝试

    try {
        Runtime runtime = Runtime.getRuntime();
        Process proc = runtime.exec("mount");
        InputStream is = proc.getInputStream();
        InputStreamReader isr = new InputStreamReader(is);
        String line;
        BufferedReader br = new BufferedReader(isr);
        while ((line = br.readLine()) != null) {
            //Filter common Linux partitions
            if (line.contains("secure"))
                continue;
            if (line.contains("asec"))
                continue;
            if (line.contains("media"))
                continue;
            if (line.contains("system") || line.contains("cache")
                || line.contains("sys") || line.contains("data")
                || line.contains("tmpfs") || line.contains("shell")
                || line.contains("root") || line.contains("acct")
                || line.contains("proc") || line.contains("misc")
                || line.contains("obb")) {
                continue;
            }

            if (line.contains("fat") || line.contains("fuse") || (line
                .contains("ntfs"))) {

                String columns[] = line.split(" ");
                if (columns != null && columns.length > 1) {
                    String path = columns[1];
                    if (path!=null&&!SdList.contains(path)&&path.contains("sd"))
                        SdList.add(columns[1]);
                }
            }
        }
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }