2017-12-13 120 views
5

Nie mogę zapisać plik obrazu w Android Oreo (8,0) api 26.
Kod jest doskonale pracuje w poziomie api 25 (7,0) i nie mogę znaleźć żadnych zmian w dokumentacji „Android 8.0 Behavior ChangesNie można zapisać pliku obrazu w aktualizacji Androida oreo. Jak to zrobić?

Oto mój kod

String root = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).toString(); 
File myrootDir = new File(root); 
if (!myrootDir.exists()) { 
    myrootDir.mkdir(); 
} 

File myDir = new File(root + "/Myimages"); 
if (!myDir.exists()) { 
    myDir.mkdir(); 
} 
final String fname = System.currentTimeMillis()+"myimage.png"; 
File file = new File(myDir, fname); 
if (file.exists()) 
    file.delete(); 
try { 
    FileOutputStream out = new FileOutputStream(file); 
    b.compress(Bitmap.CompressFormat.PNG, 100, out); 
    out.flush(); 
    out.close(); 
}catch (Exception e){ 
    Log.e("MYAPP", "exception", e); 
} 

Wyjątek jest FileNotFoundException, Nie ma takiego pliku lub katalogu. (Ale dlaczego nie w android n?)

java.io.FileNotFoundException: /storage/emulated/0/Pictures/Myimages/1513151272243myimage.png (No such file or directory) 
12-13 13:17:52.243 5839-5839/com.package.package W/System.err:  at java.io.FileOutputStream.open0(Native Method) 
12-13 13:17:52.243 5839-5839/com.package.package W/System.err:  at java.io.FileOutputStream.open(FileOutputStream.java:287) 
12-13 13:17:52.243 5839-5839/com.package.package W/System.err:  at java.io.FileOutputStream.<init>(FileOutputStream.java:223) 
12-13 13:17:52.243 5839-5839/com.package.package W/System.err:  at java.io.FileOutputStream.<init>(FileOutputStream.java:171) 
12-13 13:17:52.243 5839-5839/com.package.package W/System.err:  at com.package.package.DetailPage$12.run(DetailPage.java:737) 
12-13 13:17:52.244 5839-5839/com.package.package W/System.err:  at android.os.Handler.handleCallback(Handler.java:789) 
12-13 13:17:52.244 5839-5839/com.package.package W/System.err:  at android.os.Handler.dispatchMessage(Handler.java:98) 
12-13 13:17:52.244 5839-5839/com.package.package W/System.err:  at android.os.Looper.loop(Looper.java:164) 
12-13 13:17:52.244 5839-5839/com.package.package W/System.err:  at android.app.ActivityThread.main(ActivityThread.java:6541) 
12-13 13:17:52.244 5839-5839/com.package.package W/System.err:  at java.lang.reflect.Method.invoke(Native Method) 
12-13 13:17:52.244 5839-5839/com.package.package W/System.err:  at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240) 
12-13 13:17:52.244 5839-5839/com.package.package W/System.err:  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767) 
+2

Czy masz jakieś wyjątki? Proszę napisać tutaj – Rinav

+3

Oohh Widzę, że masz pusty blok catch, proszę dodaj logowanie do bloku catch. Najlepszą praktyką ** nigdy nie pozostawiaj pustego bloku catch. Zawsze go obsługuj ** – Rinav

+1

mogę zapisać obraz używając tego kodu w Androidzie n. ale w Androidzie o, nop :( –

Odpowiedz

5

Nie jest w rzeczywistości niewielkie, subtelne zmiany uprawnień dla aplikacji działających na i kierowania API 26.

Wcześniej aplikacje zostały automatycznie przyznane wszystkie uprawnienia w danej grupie, jeśli użytkownik udzielił co najmniej jednego pozwolenia w tej grupie. Oznacza to, że aplikacja, która uzyskała certyfikat READ_EXTERNAL_STORAGE, zostałaby mu natychmiast przekazana, niezależnie od tego, czy jednoznacznie zażądano jej od użytkownika: WRITE_EXTERNAL_STORAGE.

Od firmy Oreo w przypadku aplikacji kierowanych na interfejs API 26+ zostało to poprawione i przyznane zostaną tylko te uprawnienia, które są jawnie wymagane. Jeśli użytkownik udzielił już pozwolenia w tej samej grupie, nie będzie żadnego monitu o nowe pozwolenie, ale nadal musi zostać poproszony.

To był problem, w tym przypadku. Po przyznaniu uprawnień do Twojej aplikacji na Nougat lub niższej, automatycznie otrzymujesz także WRITE_EXTERNAL_STORAGE, bez konieczności żądania tego. Gdy spróbujesz tej samej procedury zapisywania plików w Oreo, automatycznie nie otrzymasz WRITE_EXTERNAL_STORAGE, więc zapis ostatecznie się nie powiedzie.

Po prostu dodaj konkretną prośbę o WRITE_EXTERNAL_STORAGE. Jeśli użytkownik przyznał już READ_EXTERNAL_STORAGE, nie będzie mu przeszkadzać inny monit. Ewentualnie możesz poprosić o od samego początku wyłącznie WRITE_EXTERNAL_STORAGE, co domyślnie obejmuje READ_EXTERNAL_STORAGE i zaoszczędziłoby ci dwóch oddzielnych żądań.

+1

Dziękuję bardzo :) –

1

Mam również ten sam problem i utknąłem z tym problemem od 2 miesięcy. Już wcześniej wyraziłem zgodę na WRITE_EXTERNAL_STORAGE w manifeście, a także ponownie sprawdzam, czy ma on uprawnienia do zapisu. Myślę, że to nie jest problem z pozwoleniem. Ponieważ kiedy testuję z oreo, tworzy się folder i jest uszkodzony plik obrazu w folderze, który tworzę. Z tego powodu nie przychodzi do galerii, a po zapisaniu zwraca mi obraz nie przechwycony. Otrzymuję ten problem tylko w Androidzie 7.1.1 i Oreo. Upto android 7.0 działa poprawnie. Sprawdziłem z urządzenia Samsung Galaxy Note 8 i google pikseli XL 2. Używam niestandardowy aparat z GPS i poniżej funkcji

public void onImageAvailable(ImageReader reader) { 
        Image image = null; 
        try { 
         image = reader.acquireLatestImage(); 
         ByteBuffer buffer = image.getPlanes()[0].getBuffer(); 
         byte[] bytes = new byte[buffer.capacity()]; 
         buffer.get(bytes); 
         save(bytes); 

dla obrazu bajt zapisać i zapisać funkcja zawiera poniższy kod

OutputStream output = null; 
        try { 
         output = new FileOutputStream(finalFile); 
         output.write(bytes); 
        } finally { 
         if (null != output) { 
          output.close(); 
         } 
        }