Why Do I Need The Write_external_storage Permission With Getexternalcachedir() On Android Lollipop?
My app writes (and reads) cache files to the getExternalCacheDir() location. Before Android Lollipop (API 21) I've been using this permission with success:
Solution 1:
We've seen same behaviour on API 21 (Lollipop) on a Nexus 5:
java.io.FileNotFoundException: /storage/emulated/0/Android/data/[package name]/cache/http/journal.tmp: open failed: EACCES (Permission denied)
at libcore.io.IoBridge.open(IoBridge.java:456)
at java.io.FileOutputStream.<init>(FileOutputStream.java:87)
at java.io.FileOutputStream.<init>(FileOutputStream.java:72)
at com.android.okhttp.internal.DiskLruCache.rebuildJournal(DiskLruCache.java:346)
at com.android.okhttp.internal.DiskLruCache.open(DiskLruCache.java:239)
at com.android.okhttp.HttpResponseCache.<init>(HttpResponseCache.java:140)
at android.net.http.HttpResponseCache.install(HttpResponseCache.java:199)
...
at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1011)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4518)
at android.app.ActivityThread.access$1500(ActivityThread.java:144)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1339)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5221)
at java.lang.reflect.Method.invoke(Method.java)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
Caused by: android.system.ErrnoException: open failed: EACCES (Permission denied)
at libcore.io.Posix.open(Posix.java)
at libcore.io.BlockGuardOs.open(BlockGuardOs.java:186)
at libcore.io.IoBridge.open(IoBridge.java:442)
at java.io.FileOutputStream.<init>(FileOutputStream.java:87)
at java.io.FileOutputStream.<init>(FileOutputStream.java:72)
at com.android.okhttp.internal.DiskLruCache.rebuildJournal(DiskLruCache.java:346)
at com.android.okhttp.internal.DiskLruCache.open(DiskLruCache.java:239)
at com.android.okhttp.HttpResponseCache.<init>(HttpResponseCache.java:140)
at android.net.http.HttpResponseCache.install(HttpResponseCache.java:199)
...
at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1011)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4518)
at android.app.ActivityThread.access$1500(ActivityThread.java:144)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1339)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5221)
at java.lang.reflect.Method.invoke(Method.java)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
Until Google push Android 5.0 to the AOSP we won't be able to work out if its a bug or deliberate (but undocumented) change, but I've raised this bug regardless: https://code.google.com/p/android/issues/detail?id=81357
Adding WRITE_EXTERNAL_STORAGE permission prevents the above exception being thrown, but will require end user permission to upgrade existing apps. Since our app doesn't use this permission and we don't want to add it, we're falling back to using internal cache for all except KitKat devices.
As an aside, I found this an interesting background to the changes introduced in KitKat: http://www.doubleencore.com/2014/03/android-external-storage/
Post a Comment for "Why Do I Need The Write_external_storage Permission With Getexternalcachedir() On Android Lollipop?"