FileNotFoundException 打开失败:在将图像文件保存到 android 上的内部存储期间,EPERM(不允许操作)

2022-09-01 15:28:11

当我尝试将图像保存到Android上的内部存储时,我遇到了这个问题。

public static String setImage(Bitmap image) {
    if (image != null) {
        FileOutputStream outputStream = null;
        File dir = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/Caramel");
        dir.mkdir();
        String fileName = System.currentTimeMillis() + ".jpg";
        File file = new File(dir, fileName);
        try {
            outputStream = new FileOutputStream(file);
            image.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
            outputStream.flush();
            outputStream.close();
            return fileName;
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (outputStream != null) {
                    outputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    return null;
}

一切都很好,很顺利,我可以在调试模式下看到我的位图图像,但无论如何,我得到下一个错误:

W/System.err: java.io.FileNotFoundException: /storage/emulated/0/Caramel/1587724428205.jpg: open failed: EPERM (Operation not permitted)
    W/System.err:     at libcore.io.IoBridge.open(IoBridge.java:495)
    W/System.err:     at java.io.FileOutputStream.<init>(FileOutputStream.java:235)
    W/System.err:     at java.io.FileOutputStream.<init>(FileOutputStream.java:186)
    W/System.err:     at com.example.caramel.Position.setImage(Position.java:176)
    W/System.err:     at com.example.caramel.PositionActivity.onActivityResult(PositionActivity.java:129)
    W/System.err:     at android.app.Activity.dispatchActivityResult(Activity.java:8300)
    W/System.err:     at android.app.ActivityThread.deliverResults(ActivityThread.java:4905)
    W/System.err:     at android.app.ActivityThread.handleSendResult(ActivityThread.java:4953)
    W/System.err:     at android.app.servertransaction.ActivityResultItem.execute(ActivityResultItem.java:51)
    W/System.err:     at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
    W/System.err:     at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
    W/System.err:     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2043)
    W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:106)
    W/System.err:     at android.os.Looper.loop(Looper.java:216)
    W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:7464)
    W/System.err:     at java.lang.reflect.Method.invoke(Native Method)
    W/System.err:     at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:549)
    W/System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:955)
    W/System.err: Caused by: android.system.ErrnoException: open failed: EPERM (Operation not permitted)
    W/System.err:     at libcore.io.Linux.open(Native Method)
    W/System.err:     at libcore.io.ForwardingOs.open(ForwardingOs.java:166)
    W/System.err:     at libcore.io.BlockGuardOs.open(BlockGuardOs.java:254)
    W/System.err:     at libcore.io.ForwardingOs.open(ForwardingOs.java:166)
    W/System.err:     at android.app.ActivityThread$AndroidOs.open(ActivityThread.java:7360)
    W/System.err:     at libcore.io.IoBridge.open(IoBridge.java:481)
    W/System.err:   ... 17 more

看起来,这个原因可能在我的清单.xml文件中,但我已经设置了这些权限:

<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />

谢谢你的支持,伙计们。


答案 1

我遇到了这个问题 在android 11中“:”不允许在文件名中使用。当您在文件名的末尾附加日期时,请在末尾添加“:”。因此,只需将所有“:”替换为“.”即可正常工作。

        String fileName = 
              System.currentTimeMillis().toString().replaceAll(":", ".") + ".jpg";


答案 2

作为临时修复,您可以执行以下操作:在您的文件中,在android/app/src/main/AndroidManifest.xml

<application android:label="APPNAME" android:icon="ICONNAME" ...>

添加 ,如下所示:android:requestLegacyExternalStorage="true"

<application android:label="APPNAME" android:icon="ICONNAME" android:requestLegacyExternalStorage="true">

然后,它将使用Android 10之前的请求访问存储的方式,因此您仍然可以像以前一样保存文件。

但要注意:当您将应用更新为面向 Android 11(API 级别 30)后,当您的应用在 Android 11 设备上运行时,系统会忽略 requestLegacyExternalStorage 属性,因此您的应用必须准备好支持作用域存储并为这些设备上的用户迁移应用数据。有关详细信息,请参阅 https://developer.android.com/training/data-storage/use-cases#opt-out-scoped-storage