W/System.err: java.io.FileNotFoundException: /storage/emulated/0/XRichText/1654560767490-: open failed: EPERM (Operation not permitted)
at libcore.io.IoBridge.open(IoBridge.java:575)
at java.io.FileOutputStream.(FileOutputStream.java:236)
at java.io.FileOutputStream.(FileOutputStream.java:186)
at com.example.wifibreaker.util.SDCardUtil.saveToSdCard(SDCardUtil.java:55)
at com.example.wifibreaker.activity.EditDiaryActivity 4. s u b s c r i b e ( E d i t D i a r y A c t i v i t y . j a v a : 264 ) a t i o . r e a c t i v e x . i n t e r n a l . o p e r a t o r s . o b s e r v a b l e . O b s e r v a b l e C r e a t e . s u b s c r i b e A c t u a l ( O b s e r v a b l e C r e a t e . j a v a : 40 ) a t i o . r e a c t i v e x . O b s e r v a b l e . s u b s c r i b e ( O b s e r v a b l e . j a v a : 12090 ) a t i o . r e a c t i v e x . i n t e r n a l . o p e r a t o r s . o b s e r v a b l e . O b s e r v a b l e S u b s c r i b e O n 4.subscribe(EditDiaryActivity.java:264) at io.reactivex.internal.operators.observable.ObservableCreate.subscribeActual(ObservableCreate.java:40) at io.reactivex.Observable.subscribe(Observable.java:12090) at io.reactivex.internal.operators.observable.ObservableSubscribeOn 4.subscribe(EditDiaryActivity.java:264)atio.reactivex.internal.operators.observable.ObservableCreate.subscribeActual(ObservableCreate.java:40)atio.reactivex.Observable.subscribe(Observable.java:12090)atio.reactivex.internal.operators.observable.ObservableSubscribeOnSubscribeTask.run(ObservableSubscribeOn.java:96)
at io.reactivex.Scheduler D i s p o s e T a s k . r u n ( S c h e d u l e r . j a v a : 578 ) a t i o . r e a c t i v e x . i n t e r n a l . s c h e d u l e r s . S c h e d u l e d R u n n a b l e . r u n ( S c h e d u l e d R u n n a b l e . j a v a : 66 ) a t i o . r e a c t i v e x . i n t e r n a l . s c h e d u l e r s . S c h e d u l e d R u n n a b l e . c a l l ( S c h e d u l e d R u n n a b l e . j a v a : 57 ) a t j a v a . u t i l . c o n c u r r e n t . F u t u r e T a s k . r u n ( F u t u r e T a s k . j a v a : 266 ) a t j a v a . u t i l . c o n c u r r e n t . S c h e d u l e d T h r e a d P o o l E x e c u t o r DisposeTask.run(Scheduler.java:578) at io.reactivex.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:66) at io.reactivex.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:57) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.ScheduledThreadPoolExecutor DisposeTask.run(Scheduler.java:578)atio.reactivex.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:66)atio.reactivex.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:57)atjava.util.concurrent.FutureTask.run(FutureTask.java:266)atjava.util.concurrent.ScheduledThreadPoolExecutorScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor W o r k e r . r u n ( T h r e a d P o o l E x e c u t o r . j a v a : 641 ) a t j a v a . l a n g . T h r e a d . r u n ( T h r e a d . j a v a : 920 ) W / S y s t e m . e r r : C a u s e d b y : a n d r o i d . s y s t e m . E r r n o E x c e p t i o n : o p e n f a i l e d : E P E R M ( O p e r a t i o n n o t p e r m i t t e d ) a t l i b c o r e . i o . L i n u x . o p e n ( N a t i v e M e t h o d ) a t l i b c o r e . i o . F o r w a r d i n g O s . o p e n ( F o r w a r d i n g O s . j a v a : 567 ) a t l i b c o r e . i o . B l o c k G u a r d O s . o p e n ( B l o c k G u a r d O s . j a v a : 273 ) a t l i b c o r e . i o . F o r w a r d i n g O s . o p e n ( F o r w a r d i n g O s . j a v a : 567 ) a t a n d r o i d . a p p . A c t i v i t y T h r e a d Worker.run(ThreadPoolExecutor.java:641) at java.lang.Thread.run(Thread.java:920) W/System.err: Caused by: android.system.ErrnoException: open failed: EPERM (Operation not permitted) at libcore.io.Linux.open(Native Method) at libcore.io.ForwardingOs.open(ForwardingOs.java:567) at libcore.io.BlockGuardOs.open(BlockGuardOs.java:273) at libcore.io.ForwardingOs.open(ForwardingOs.java:567) at android.app.ActivityThread Worker.run(ThreadPoolExecutor.java:641)atjava.lang.Thread.run(Thread.java:920)W/System.err:Causedby:android.system.ErrnoException:openfailed:EPERM(Operationnotpermitted)atlibcore.io.Linux.open(NativeMethod)atlibcore.io.ForwardingOs.open(ForwardingOs.java:567)atlibcore.io.BlockGuardOs.open(BlockGuardOs.java:273)atlibcore.io.ForwardingOs.open(ForwardingOs.java:567)atandroid.app.ActivityThreadAndroidOs.open(ActivityThread.java:8080)
at libcore.io.IoBridge.open(IoBridge.java:561)
… 15 more
原因
注意:在 Android 11(API 级别 30)及更高版本中,应用无法在外部存储设备上创建自己的应用专用目录。
解决办法(3种方案):
- 降低SDK至29或以下(可实现随意改写目录创建文件)
- SDK保留30那么加入:
requestLegacyExternalStorage= "true"
但是目标路径仅局限于内部存储路径下的
public static String DIRECTORY_ALARMS = "Alarms";
public static String DIRECTORY_DCIM = "DCIM";
public static String DIRECTORY_DOCUMENTS = "Documents";
public static String DIRECTORY_DOWNLOADS = "Download";
public static String DIRECTORY_MOVIES = "Movies";
public static String DIRECTORY_MUSIC = "Music";
public static String DIRECTORY_NOTIFICATIONS = "Notifications";
public static String DIRECTORY_PICTURES = "Pictures";
public static String DIRECTORY_PODCASTS = "Podcasts";
public static String DIRECTORY_RINGTONES = "Ringtones";
这几个公有文件夹下创建
3. sdk>=31,方案二会失效,官方给出的方案:
创建缓存文件
如需将应用专属文件添加到外部存储空间中的缓存,请获取对 externalCacheDir 的引用:
File externalCacheFile = new File(context.getExternalCacheDir(), filename);