2014-11-19 23 views
9

La mia app scrive (e legge) i file di cache nella posizione getExternalCacheDir(). Prima di Android Lollipop (API 21) Sto usando questa autorizzazione con successo:Perché ho bisogno dell'autorizzazione WRITE_EXTERNAL_STORAGE con getExternalCacheDir() su Android Lollipop?

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

Il maxSdkVersion è lì perché questa autorizzazione non dovrebbe essere necessario dopo l'API v18: http://developer.android.com/reference/android/Manifest.permission.html#WRITE_EXTERNAL_STORAGE

Ma su Android Lollipop (5.0) ricevo un permesso di accesso in questo modo (con la mia uscita di log per mostrare il percorso effettivo utilizzato):

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) 

vedo questo sia nell'emulatore e sul mio Nexus 4. qualcosa è cambiato, o Stavo facendo qualcosa di negativo g tutto insieme? Voglio solo accedere alla cache della mia app.

Aggiornamento: Ora lo vedo solo sul mio dispositivo (Nexus 4 con Android 5.1.1 standard, che ha avuto anche un nuovo reflash Android da quando ho avuto questo problema per la prima volta). Non vedo più questo nell'emulatore - ovviamente le immagini di sistema sono state aggiornate più volte.

+0

Se non aggiungere questo androide: maxSdkVersion = proprietà "18", allora funziona? –

+0

Sì. Devo sempre richiedere WRITE_EXTERNAL_STORAGE per farlo funzionare. Mi chiedo se c'è un modo per dire che è necessario per <18 but > 20, se è davvero necessario per 21 (Lollipop). – murrayc

+0

Sì come da documentazione A partire dal livello API 19, questa autorizzazione non è richiesta per leggere/scrivere file nelle directory specifiche dell'applicazione restituite da getExternalFilesDir (String) e getExternalCacheDir() in modo da non richiedere questa autorizzazione 19 o API, ma la conclusione è non funziona senza questa autorizzazione. –

risposta

5

Abbiamo visto lo stesso comportamento su API 21 (Lollipop) su un 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) 

Fino Google spingere Android 5.0 per l'AOSP non saremo in grado di capire se la sua un bug o deliberata (ma non documentato) il cambiamento, ma ho sollevato questo bug indipendentemente: https://code.google.com/p/android/issues/detail?id=81357

Aggiunta il permesso WRITE_EXTERNAL_STORAGE impedisce l'eccezione di cui sopra essere gettati, ma richiederà il permesso all'utente finale di aggiornare le applicazioni esistenti. Dato che la nostra app non usa questa autorizzazione e non vogliamo aggiungerla, stiamo ricadendo sull'uso della cache interna per tutti tranne i dispositivi KitKat.

Per inciso, ho trovato questo un background interessante per le modifiche introdotte nel KitKat: http://www.doubleencore.com/2014/03/android-external-storage/

+0

Apprezzo la conferma che non sono l'unico con questo problema, ma questo mi sembra solo una riaffermazione del problema piuttosto che una risposta. – murrayc

+0

@murrayc Ho anche sollevato il bug con Google, anche se ovviamente era troppo tardi per correggere Lollipop perché era già in circolazione.Il fallback per usare solo la cache interna era sufficiente per le nostre esigenze. – fingertricks

+0

Sì, grazie. Che segno hai che lo abbiano sistemato, troppo tardi o no? – murrayc