为什么我需要在 Android Lollipop 上通过 getExternalCacheDir() 获得 WRITE_EXTERNAL_STORAGE 权限? [英] Why do I need the WRITE_EXTERNAL_STORAGE permission with getExternalCacheDir() on Android Lollipop?

查看:52
本文介绍了为什么我需要在 Android Lollipop 上通过 getExternalCacheDir() 获得 WRITE_EXTERNAL_STORAGE 权限?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的应用程序将缓存文件写入(和读取)到 getExternalCacheDir() 位置.在 Android Lollipop (API 21) 之前,我一直在成功使用此权限:

My app writes (and reads) cache files to the getExternalCacheDir() location. Before Android Lollipop (API 21) I've been using this permission with success:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="18" />

有 maxSdkVersion 是因为在 API v18 之后不需要这个权限:http://developer.android.com/reference/android/Manifest.permission.html#WRITE_EXTERNAL_STORAGE

The maxSdkVersion is there because this permission shouldn't be needed after API v18: http://developer.android.com/reference/android/Manifest.permission.html#WRITE_EXTERNAL_STORAGE

但是在 Android Lollipop (5.0) 上,我获得了这样的访问权限(我的日志输出显示了使用的实际路径):

But on Android Lollipop (5.0) I'm getting an access permission like so (with my log output to show the actual path used):

11-19 13:01:59.257    4462-4541/com.murrayc.galaxyzoo.app E/android-galaxyzoo﹕     createCacheFile(): IOException for filename=/storage/emulated/0/Android/data/com.murrayc.galaxyzoo.app/cache/52
    java.io.IOException: open failed: EACCES (Permission denied)
            at java.io.File.createNewFile(File.java:941)
            at com.murrayc.galaxyzoo.app.provider.ItemsContentProvider.createCacheFile(ItemsContentProvider.java:528)

我在模拟器和我的 Nexus 4 上都看到了这一点.有什么改变,还是我一直做错了什么?我只想访问我自己的应用缓存.

I see this both in the emulator and on my Nexus 4. Has something changed, or was I doing something wrong all along? I just want to access my own app's cache.

更新:我现在只能在我的设备上看到这个(Nexus 4 运行标准的 Android 5.1.1,自从我第一次遇到这个问题以来,它甚至重新刷新了 Android).我不再在模拟器中看到这个 - 当然系统映像已经更新了几次.

Update: I now see this only on my device (Nexus 4 running the standard Android 5.1.1, which has even had a fresh Android reflash since I first had this problem). I no longer see this in the emulator - of course the system images have been updated several times.

推荐答案

我们在 Nexus 5 上的 API 21 (Lollipop) 上看到了相同的行为:

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)

在 Google 将 Android 5.0 推送到 AOSP 之前,我们将无法确定它是错误还是有意(但未记录)的更改,但无论如何我都提出了这个错误:https://code.google.com/p/android/issues/detail?id=81357

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

添加 WRITE_EXTERNAL_STORAGE 权限可防止引发上述异常,但需要最终用户权限才能升级现有应用.由于我们的应用不使用此权限并且我们不想添加它,因此我们将回退到对除 KitKat 设备之外的所有设备使用内部缓存.

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.

顺便说一句,我发现这是 KitKat 中引入的更改的有趣背景:http://www.doubleencore.com/2014/03/android-external-storage/

As an aside, I found this an interesting background to the changes introduced in KitKat: http://www.doubleencore.com/2014/03/android-external-storage/

这篇关于为什么我需要在 Android Lollipop 上通过 getExternalCacheDir() 获得 WRITE_EXTERNAL_STORAGE 权限?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆