2014-11-19 20 views
9

Moja aplikacja zapisuje (i czyta) pliki pamięci podręcznej do lokalizacji getExternalCacheDir(). Przed Android Lollipop (API 21) Używam tego uprawnienia z sukcesu:Dlaczego potrzebuję uprawnienia WRITE_EXTERNAL_STORAGE z getExternalCacheDir() na Android Lollipop?

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

maxSdkVersion jest tam, ponieważ to uprawnienie nie powinno być potrzebne po API V18: http://developer.android.com/reference/android/Manifest.permission.html#WRITE_EXTERNAL_STORAGE

Ale na Androida Lollipop (5.0) Otrzymuję uprawnienia dostępu (tak jak z moim wyjściu dziennika, aby pokazać rzeczywistą ścieżkę używaną):

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) 

widzę to zarówno w emulatorze i na moim Nexus 4. czy coś się zmieniło, czy czy robiłem coś wron g cały czas? Chcę tylko uzyskać dostęp do pamięci podręcznej mojej aplikacji.

Aktualizacja: Teraz widzę to tylko w moim urządzeniu (Nexus 4 z systemem Android 5.1.1 standardowego, który miał nawet świeże Android wgra odkąd pierwszy miał ten problem). Nie widzę już tego w emulatorze - oczywiście obrazy systemu zostały zaktualizowane kilka razy.

+0

Jeśli nie dodać ten android: maxSdkVersion = „18” Właściwości to działa? –

+0

Tak. Muszę zawsze prosić WRITE_EXTERNAL_STORAGE, aby to działało. Zastanawiam się, czy istnieje sposób, aby powiedzieć, że jest to potrzebne dla <18 but > 20, jeśli jest to naprawdę potrzebne dla 21 (Lollipop). – murrayc

+0

Tak jak w dokumentacji Począwszy od poziomu interfejsu API 19, to uprawnienie nie jest wymagane do odczytu/zapisu plików w katalogach aplikacji zwróconych przez getExternalFilesDir (String) i getExternalCacheDir(), więc nie wymagamy tego uprawnienia 19 lub wyższego API, ale wniosek jest nie działa bez tego pozwolenia. –

Odpowiedz

5

Widzieliśmy samo zachowanie na API 21 (Lollipop) na Nexusie 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) 

Do pchania Google Android 5.0 do AOSP nie będziemy w stanie wypracować jeśli jego błąd lub celowe (ale nieudokumentowane) zmiana, ale ja podniósł ten błąd niezależnie: https://code.google.com/p/android/issues/detail?id=81357

Dodawanie pozwolenie WRITE_EXTERNAL_STORAGE zapobiega powyższy wyjątek jest rzucony, ale będzie wymagać zgody użytkownika końcowego uaktualnić istniejące aplikacje. Ponieważ nasza aplikacja nie używa tego pozwolenia i nie chcemy go dodawać, cofamy się do korzystania z wewnętrznej pamięci podręcznej dla wszystkich urządzeń z wyjątkiem KitKat.

Tak na marginesie, uważam to za ciekawe tło do zmian wprowadzonych w KitKat: http://www.doubleencore.com/2014/03/android-external-storage/

+0

Doceniam potwierdzenie, że nie jestem jedyny z tym problemem, ale wydaje się, że jest to po prostu przekształcenie problemu, a nie odpowiedź. – murrayc

+0

@murrayc Podniosłem również błąd z Google, chociaż oczywiście było już za późno, by naprawić Lollipopa, ponieważ było już na wolności.Zastąpienie tylko wewnętrznej pamięci podręcznej było wystarczające dla naszych potrzeb. – fingertricks

+0

Tak, dziękuję. Jaki masz znak, że to naprawili, za późno, czy nie? – murrayc