【问题标题】:Saving an image after getting folder from Storage Access Framework UI从 Storage Access Framework UI 获取文件夹后保存图像
【发布时间】:2018-02-06 01:40:14
【问题描述】:

我使用 Storage Access Framework 为我的应用程序设置了一个首选项以选择保存文件夹。获取 uri onActivityResult 后,我将其作为字符串保存到 SharedPreferences,并在需要保存时保存图像。

我正在使用这个方法成功保存图片。

public void saveImageWithDocumentFile(String uriString, String mimeType, String name) {
    isImageSaved = false;
    try {
        Uri uri = Uri.parse(uriString);
        DocumentFile pickedDir = DocumentFile.fromTreeUri(this, uri);
        DocumentFile file = pickedDir.createFile(mimeType, name);
        OutputStream out = getContentResolver().openOutputStream(file.getUri());
        isImageSaved = mBitmap.compress(CompressFormat.JPEG, 100, out);
        out.close();

    } catch (IOException e) {
        throw new RuntimeException("Something went wrong : " + e.getMessage(), e);
    }
    Toast.makeText(MainActivity.this, "Image saved  " + isImageSaved, Toast.LENGTH_SHORT).show();
}

如果用户删除使用 SAF 选择的文件夹,iget null DocumentFile file 和应用程序崩溃。我的第一个问题是如何在不再次打开 SAF ui 的情况下检查文件夹是否存在。

我也想用 ParcelFileDescriptor 用这个方法保存同一张图片

public void saveImageWithParcelFileDescriptor(String folder, String name) {
    if (mBitmap == null) {
        Toast.makeText(MainActivity.this, "", Toast.LENGTH_SHORT).show();
        return;
    }
    String image = folder + File.separator + name + ".jpg";
    Toast.makeText(MainActivity.this, "image " + image, Toast.LENGTH_LONG).show();

    Uri uri = Uri.parse(image);
    ParcelFileDescriptor pfd = null;
    FileOutputStream fileOutputStream = null;
    try {
        pfd = getContentResolver().openFileDescriptor(uri, "w");
        fileOutputStream = new FileOutputStream(pfd.getFileDescriptor());
        mBitmap.compress(CompressFormat.JPEG, 100, fileOutputStream);

    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } finally {
        if (pfd != null) {
            try {
                pfd.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        if (fileOutputStream != null) {
            try {
                fileOutputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    Toast.makeText(MainActivity.this, "Image saved  " + isImageSaved, Toast.LENGTH_SHORT).show();

}

我得到java.lang.IllegalArgumentException: Invalid URI: content://com.android.externalstorage.documents/tree/612E-B7BF%3Aname/imagePFD.jpg 在线pfd = getContentResolver().openFileDescriptor(uri, "w");

这就是我调用此方法的方式,currentFolder 是我在第一种方法中使用意图和相同文件夹获得的文件夹。

saveImageWithParcelFileDescriptor(currentFolder, "imagePFD");

我该如何解决这个问题,哪种方法更可取,为什么?

【问题讨论】:

    标签: android storage-access-framework


    【解决方案1】:

    如何检查文件夹是否存在

    DocumentFile 有一个 exists() 方法。理论上,pickedDir.exists() 应该会告诉你它是否存在。实际上,这取决于存储提供商。

    我也想用 ParcelFileDescriptor 用这个方法保存同一张图片

    该代码有错误:

    • 您不能使用grantUriPermission() 授予自己权限

    • 您不能通过串联创建任意的Uri 值,尤其是对于不属于您的提供者

    我该如何解决这个问题

    删除它。

    哪种方法更可取

    第一个。

    为什么?

    第一个可以工作,也许稍作调整。第二个没有机会工作。

    【讨论】:

    • 是的,只要保存的文件夹存在,第一个就可以工作。我将使用 documentFile.exist() 检查文件夹是否存在。没有办法用自定义名称和 ParcelFileDescriptor 保存图像吗?
    • @FatihOzcan:欢迎您将第一个代码 sn-p 中的 OutputStream out = getContentResolver().openOutputStream(file.getUri()) 替换为 getContentResolver().openFileDescriptor(file.getUri(), "w"),然后使用 ParcelFileDescriptor。我不知道有什么好处,结果会比你的第一个代码 sn-p 长得多,结果不会很像你的第二个代码 sn-p。关键是使用createFile(),所以存储提供者就是你写的Uri
    • 我删除了grantUriPermission()。获得许可或持久许可仅对您在onActivityResult 上获得的uri 有效?文件上没有这方面的信息。在文档上“您的应用访问的最新 URI 可能不再有效 - 另一个应用可能已删除或修改了文档。因此,您应该始终调用 getContentResolver().takePersistableUriPermission() 来检查最新数据。”,但是如何使用此方法检查文件夹是否存在。它不返回任何东西。
    • 我还有一个问题。难道没有办法用 ParceFileDescriptor 编写自定义文件吗?如果不使用 OutputStream,就无法将位图保存到设备或 sd 卡。 ParcelFileDescriptor 是否用于编写自定义文件?我不知道如何在第二种方法中将 OutputStrem 与 ParcelFileDescriptor 交换
    • @FatihOzcan:“获得许可或持久许可仅对您在 onActivityResult 上获得的 uri 有效?” -- 您可以调用takePersistableUriPermission() 上由存储访问框架操作传递给onActivityResult()Uri 值。您应该也可以将它与DocumentFile(例如createFile())返回的Uri 值一起使用,尽管我没有尝试过。 “我如何使用这种方法检查一个文件夹是否存在”——它会抛出一个SecurityException,IIRC。
    猜你喜欢
    • 1970-01-01
    • 2021-07-20
    • 1970-01-01
    • 1970-01-01
    • 2022-06-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-04
    相关资源
    最近更新 更多