android11 图片压缩保存失败的解决办法

(笔者安卓11)有个图片上传的业务,由于后台上传限制了图片大小,所以这里要进行一次压缩。

压缩后保存到指定文件夹然后上传,代码如下

  File outputFile = new File(targetPath);
        try {
            if (!outputFile.exists()) {
                outputFile.getParentFile().mkdirs();
            } else {
                outputFile.delete();
            }
            FileOutputStream out = new FileOutputStream(outputFile);
            bm.compress(Bitmap.CompressFormat.JPEG, quality, out);
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
            return oldFile;
        }

第一天运行,正常。第二天同样的手机,同样的代码,出现如下错误:

 java.io.FileNotFoundException: /storage/emulated/0/Pictures/WeiXin/microMsg.1613541990299.jpg: open failed: EACCES (Permission denied)
2021-04-23 22:49:05.954 8502-10535/com.yuran.huojushou W/System.err:     at libcore.io.IoBridge.open(IoBridge.java:492)
2021-04-23 22:49:05.954 8502-10535/com.yuran.huojushou W/System.err:     at java.io.FileOutputStream.<init>(FileOutputStream.java:236)
2021-04-23 22:49:05.954 8502-10535/com.yuran.huojushou W/System.err:     at java.io.FileOutputStream.<init>(FileOutputStream.java:186)
2021-04-23 22:49:05.954 8502-10535/com.yuran.huojushou W/System.err:     at com.yuran.huojushou.util.BitmapUtil.compressImage(BitmapUtil.java:147)
2021-04-23 22:49:05.954 8502-10535/com.yuran.huojushou W/System.err:     at com.yuran.huojushou.presenter.UserInfoPresenter$changeAvatar$1.call(UserInfoPresenter.kt:49)
2021-04-23 22:49:05.954 8502-10535/com.yuran.huojushou W/System.err:     at com.yuran.huojushou.presenter.UserInfoPresenter$changeAvatar$1.call(UserInfoPresenter.kt:33)
2021-04-23 22:49:05.954 8502-10535/com.yuran.huojushou W/System.err:     at rx.internal.operators.OnSubscribeMap$MapSubscriber.onNext(OnSubscribeMap.java:69)
2021-04-23 22:49:05.954 8502-10535/com.yuran.huojushou W/System.err:     at rx.internal.util.ScalarSynchronousObservable$WeakSingleProducer.request(ScalarSynchronousObservable.java:276)
2021-04-23 22:49:05.954 8502-10535/com.yuran.huojushou W/System.err:     at rx.internal.operators.OperatorSubscribeOn$SubscribeOnSubscriber$1.request(OperatorSubscribeOn.java:109)
2021-04-23 22:49:05.954 8502-10535/com.yuran.huojushou W/System.err:     at rx.Subscriber.setProducer(Subscriber.java:209)
2021-04-23 22:49:05.955 8502-10535/com.yuran.huojushou W/System.err:     at rx.Subscriber.setProducer(Subscriber.java:205)
2021-04-23 22:49:05.955 8502-10535/com.yuran.huojushou W/System.err:     at rx.internal.operators.OperatorSubscribeOn$SubscribeOnSubscriber.setProducer(OperatorSubscribeOn.java:105)
2021-04-23 22:49:05.955 8502-10535/com.yuran.huojushou W/System.err:     at rx.internal.operators.OnSubscribeMap$MapSubscriber.setProducer(OnSubscribeMap.java:102)
2021-04-23 22:49:05.955 8502-10535/com.yuran.huojushou W/System.err:     at rx.internal.operators.OnSubscribeMap$MapSubscriber.setProducer(OnSubscribeMap.java:102)
2021-04-23 22:49:05.955 8502-10535/com.yuran.huojushou W/System.err:     at rx.internal.util.ScalarSynchronousObservable$JustOnSubscribe.call(ScalarSynchronousObservable.java:138)
2021-04-23 22:49:05.955 8502-10535/com.yuran.huojushou W/System.err:     at rx.internal.util.ScalarSynchronousObservable$JustOnSubscribe.call(ScalarSynchronousObservable.java:129)
2021-04-23 22:49:05.955 8502-10535/com.yuran.huojushou W/System.err:     at rx.Observable.unsafeSubscribe(Observable.java:10256)
2021-04-23 22:49:05.955 8502-10535/com.yuran.huojushou W/System.err:     at rx.internal.operators.OnSubscribeMap.call(OnSubscribeMap.java:48)
2021-04-23 22:49:05.955 8502-10535/com.yuran.huojushou W/System.err:     at rx.internal.operators.OnSubscribeMap.call(OnSubscribeMap.java:33)
2021-04-23 22:49:05.955 8502-10535/com.yuran.huojushou W/System.err:     at rx.Observable.unsafeSubscribe(Observable.java:10256)
2021-04-23 22:49:05.955 8502-10535/com.yuran.huojushou W/System.err:     at rx.internal.operators.OnSubscribeMap.call(OnSubscribeMap.java:48)
2021-04-23 22:49:05.955 8502-10535/com.yuran.huojushou W/System.err:     at rx.internal.operators.OnSubscribeMap.call(OnSubscribeMap.java:33)
2021-04-23 22:49:05.955 8502-10535/com.yuran.huojushou W/System.err:     at rx.Observable.unsafeSubscribe(Observable.java:10256)
2021-04-23 22:49:05.955 8502-10535/com.yuran.huojushou W/System.err:     at rx.internal.operators.OperatorSubscribeOn$SubscribeOnSubscriber.call(OperatorSubscribeOn.java:100)
2021-04-23 22:49:05.955 8502-10535/com.yuran.huojushou W/System.err:     at rx.internal.schedulers.CachedThreadScheduler$EventLoopWorker$1.call(CachedThreadScheduler.java:230)
2021-04-23 22:49:05.955 8502-10535/com.yuran.huojushou W/System.err:     at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:55)
2021-04-23 22:49:05.956 8502-10535/com.yuran.huojushou W/System.err:     at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:462)
2021-04-23 22:49:05.956 8502-10535/com.yuran.huojushou W/System.err:     at java.util.concurrent.FutureTask.run(FutureTask.java:266)
2021-04-23 22:49:05.956 8502-10535/com.yuran.huojushou W/System.err:     at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301)
2021-04-23 22:49:05.956 8502-10535/com.yuran.huojushou W/System.err:     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
2021-04-23 22:49:05.956 8502-10535/com.yuran.huojushou W/System.err:     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
2021-04-23 22:49:05.956 8502-10535/com.yuran.huojushou W/System.err:     at java.lang.Thread.run(Thread.java:923)
2021-04-23 22:49:05.956 8502-10535/com.yuran.huojushou W/System.err: Caused by: android.system.ErrnoException: open failed: EACCES (Permission denied)
2021-04-23 22:49:05.956 8502-10535/com.yuran.huojushou W/System.err:     at libcore.io.Linux.open(Native Method)
2021-04-23 22:49:05.956 8502-10535/com.yuran.huojushou W/System.err:     at libcore.io.ForwardingOs.open(ForwardingOs.java:166)
2021-04-23 22:49:05.956 8502-10535/com.yuran.huojushou W/System.err:     at libcore.io.BlockGuardOs.open(BlockGuardOs.java:254)
2021-04-23 22:49:05.956 8502-10535/com.yuran.huojushou W/System.err:     at libcore.io.ForwardingOs.open(ForwardingOs.java:166)
2021-04-23 22:49:05.957 8502-10535/com.yuran.huojushou W/System.err:     at android.app.ActivityThread$AndroidOs.open(ActivityThread.java:7871)
2021-04-23 22:49:05.957 8502-10535/com.yuran.huojushou W/System.err:     at libcore.io.IoBridge.open(IoBridge.java:478)
2021-04-23 22:49:05.957 8502-10535/com.yuran.huojushou W/System.err: 	... 31 more

呐尼?说我没权限?怎么可能,我静态动态全都申请了!!必不可能

百度说要设置

android:requestLegacyExternalStorage="true"

尝试后还是不行。最后去了一趟官网,官网是这样说的:

  • 内部存储空间目录:这些目录既包括用于存储持久性文件的专属位置,也包括用于存储缓存数据的其他位置。系统会阻止其他应用访问这些位置,并且在 Android 10(API 级别 29)及更高版本中,系统会对这些位置进行加密。这些特征使得这些位置非常适合存储只有应用本身才能访问的敏感数据。

  • 外部存储空间目录:这些目录既包括用于存储持久性文件的专属位置,也包括用于存储缓存数据的其他位置。虽然其他应用可以在具有适当权限的情况下访问这些目录,但存储在这些目录中的文件仅供您的应用使用。如果您明确打算创建其他应用能够访问的文件,您的应用应改为将这些文件存储在外部存储空间的共享存储空间部分。

 

然后尝试了一下保存在内部空间:

使用 File API 访问和存储文件:

File file = new File(context.getFilesDir(), filename);

调用 openFileOutput() 获取会写入 filesDir 目录中的文件的 FileOutputStream

String filename = "myfile";
String fileContents = "Hello world!";
try (FileOutputStream fos = context.openFileOutput(filename, Context.MODE_PRIVATE)) {
    fos.write(fileContents.toByteArray());
}

注意:在搭载 Android 7.0(API 级别 24)或更高版本的设备上,除非您将 Context.MODE_PRIVATE 文件模式传递到 openFileOutput(),否则会发生 SecurityException

如需允许其他应用访问存储在内部存储空间内此目录中的文件,请使用具有 FLAG_GRANT_READ_URI_PERMISSION 属性的 FileProvider

最后代码修改为:

  //创建文件
        File outputFile;
        String newimgname=临时保存的图片名称 + ".jpg";
        try {
            File dir = new File(MyApplication.Companion.get_context().getExternalFilesDir(null).getPath());
            if (!dir.exists()) {
                dir.mkdirs();
            }
            outputFile = new File(MyApplication.Companion.get_context().getFilesDir(), newimgname);
            if (!outputFile.exists()) {
                outputFile.getParentFile().mkdirs();
            }
            Log.e("111", outputFile.getPath());
            FileOutputStream out = MyApplication.Companion.get_context().openFileOutput(newimgname, Context.MODE_PRIVATE);
            bm.compress(Bitmap.CompressFormat.JPEG, quality, out);
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
            return oldFile;
        }

完美解决!!!!

应该还可以保存在共享存储空间,但项目紧,没有研究

MediaStore:https://developer.android.google.cn/reference/android/provider/MediaStore

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值