„Kanwa: próba narysowania zbyt dużej mapy bitowej”, gdy rozmiar wyświetlacza systemu Android N jest ustawiony na większy niż Mały

83

Mam opublikowaną aplikację, która ulega awarii podczas uruchamiania systemu Android N, gdy nowo wprowadzone Display sizeustawienie systemu operacyjnego ma zbyt dużą wartość.

Kiedy patrzę w logcat, widzę następujący komunikat:

java.lang.RuntimeException: Canvas: trying to draw too large(106,975,232 bytes) bitmap.

W mojej pierwszej aktywności prześledziłem problem do ImageView, który pokazuje ładny, duży obraz tła. Obraz, o którym mowa, ma rozmiar 2048x1066 i znajduje się w moim drawableskatalogu ogólnym , więc bez względu na gęstość będzie używany.

Wszystko działa dobrze, gdy Display sizejest to ustawienie Small. Ale kiedy podchodzę Default, przestaje działać. Jeśli następnie zamienię obraz na mniejszy, działa Default, ale jeśli podejdę do Large, przestaje działać.

Domyślam się, że dostosowanie w Display sizegórę powoduje, że Twoje urządzenie zachowuje się jak fizycznie mniejsze urządzenie z większą gęstością pikseli. Ale nie rozumiem, co mam tutaj zrobić. Jeśli wstawię stopniowo mniejsze obrazy dla coraz wyższych rozdzielczości, nie będzie to dobrze wyglądać na faktycznie dużych wyświetlaczach. A może czegoś nie rozumiem?

Wszelkie wskazówki byłyby bardzo mile widziane.

Brian Rak
źródło
25
„Obraz, o którym mowa, ma rozmiar 2048x1066 i znajduje się w moim ogólnym katalogu drawables, więc bez względu na gęstość ten obraz będzie używany” - res/drawable/to synonim res/drawable-mdpi/. Jeśli chcesz, aby obraz nie był skalowany na podstawie gęstości, użyj res/drawable-nodpi/lubres/drawable-anydpi/ .
CommonsWare
3
„Czy chcesz powiedzieć, że obraz o wymiarach 100x100 pikseli znajdujący się w różnych katalogach zasobów jest w rzeczywistości skalowany w celu utworzenia wirtualnej wersji o różnej rozdzielczości, zanim przejdzie do układu?” - to zależy od posiadanych gęstości i urządzenia, na którym pracujesz. Jeśli istnieje dokładne dopasowanie, nic nie jest ponownie próbkowane. Jeśli nie ma dokładnego dopasowania, obraz z pobliskiej gęstości jest ponownie próbkowany. Tak więc, jeśli masz tylko res/drawable/foo.png(aka, res/drawable-mdpi/foo.png), a twoje urządzenie jest xhdpi, obraz zostanie podwojony wzdłuż obu osi, zajmując 4x pamięć.
CommonsWare
4
Wartość 106975232 w twoim błędzie jest dokładnie 49-krotna rozdzielczością obrazu, co oznacza 7-krotne ponowne próbkowanie wzdłuż obu osi. To dużo więcej, niż bym się spodziewał. Nie miałem jeszcze okazji bawić się ustawieniami rozmiaru wyświetlacza w Androidzie 7.0, więc dodam to do mojej stale rosnącej listy rzeczy do zrobienia ...
CommonsWare
6
Niezły chwyt na 49x! Myślę, że potrafię wyjaśnić, dlaczego jest tak wysoko. Pamiętaj, że ta liczba to bajty. Ten obraz jest 24-bitowy, ale prawdopodobnie jest odczytywany z prędkością 32 bitów na piksel. To dałoby 8732672 bajtów pamięci, co daje dokładnie 12,25 razy, co z kolei oznacza 3,5-krotne skalowanie wzdłuż każdej osi. To urządzenie ma rozmiar xxhdpi, więc wydaje się, że może być w porządku. Tak czy inaczej, nie miałem pojęcia, że ​​zasoby zostaną ponownie próbkowane w ten sposób. Dziękuję za pomoc! (Nawiasem mówiąc, przeniesienie obrazu do drawable-nodpi rzeczywiście to naprawia.)
Brian Rak,
1
Naprawdę powinieneś zaakceptować odpowiedź Johana
S. Jacob Powell

Odpowiedzi:

167

W moim przypadku rozwiązaniem było przeniesienie (hi-res) splash bitmap z drawable do drawable-xxhdpi .

Miałem ten sam problem. Nie podejrzewałem, że problem stanowi mój ekran powitalny, ponieważ jest on wyświetlany po uruchomieniu aplikacji, ale okazało się, że problem stanowi ekran powitalny.

Ekran powitalny w moim przypadku ma rozdzielczość xxhdpi i został omyłkowo umieszczony w folderze do rysowania , zamiast do drawable-xxhdpi . To sprawiło, że Android założył, że ekran powitalny ma rozdzielczość mdpi i skaluje obraz do 3 * 3 razy większy od wymaganego rozmiaru i próbuje utworzyć bitmapę.

Johan Franzén
źródło
1
Zgaduję: więc android skaluje obraz z xxhdpi do hdpi, na przykład, aby był jaśniejszy? jak powiedziałeś, na przykład od 3 * 3 -> 1/1 do 1/3?
Ninja Coding,
Jak zauważa kalsara Magamage, jest to teraz mipmap-xxhdpi.
Dana Robinson
37

Rozwiązałem problem po dodaniu poniższego kodu do tagu aplikacji pliku Manifest pomiędzy liniami android :.

android:hardwareAccelerated="false"
CHAMCHOUN
źródło
3
Cóż, po spędzeniu kilku godzin to rozwiązanie działa na problemy mobilne Xiaomi i Samsung.
Shihab Uddin
4
Spowoduje to wyłączenie wszystkich podniesień CardView. Dlatego właściwym rozwiązaniem byłoby przeskalowanie mapy bitowej do mniejszego rozmiaru.
Sachin Soma,
1
Zamiast wyłączania akceleracji sprzętowej na poziomie aplikacji, bardziej przydatne będzie sterowanie nią w Aktywności, Okno, Poziom widoku.
Mukhammadsher
1
Ale po wykonaniu tej czynności pojawia się inny problem android:hardwareAccelerated="false" . pokazujący dziwny widok na jakimś urządzeniu, które ma poziom API poniżej 22.
Prince Dholakiya
3
Nie rób tego, spowalnia to twoją aplikację.
Curio
11

Nie wiem, czy to komuś pomogło, ale zostawię to tutaj. W moim przypadku - problem występował tylko na urządzeniach Sumsung z Androidem 7, a problem był w proporcjach ekranu powitalnego. po zmianie wysokości na 1024 px - wszystko działa dobrze

kazimad
źródło
Moim problemem była mapa bitowa (jpg, png) w folderze do rysowania (bez sufiksu). To moja głupota, ale może komuś to pomoże :-)
gingo
To jest pomocne! Ten sam problem tylko Samsung ... Co miałeś najpierw i jak to naprawiłeś?
M'hamed
Czy próbujesz załadować obrazy z adresu URL. Mam ten sam problem tylko z Samsungiem Galaxy S6 na Androidzie 7. Ładuję obrazy w RecyclerView. Nadal nie mogę tego rozgryźć. @ M'hamed
Rohit Singh
9

Przenieś obraz w formacie do rysowania do mipmap-xxhdpi.Twój obraz jest w formacie bitmapy, więc powinieneś umieścić go w folderze mipmap, wtedy zadziała

kalsara Magamage
źródło
1
AFAIK, folder mipmap jest przeznaczony tylko dla ikon programu uruchamiającego. Nigdy nie użyłem go do niczego innego. Zobacz stackoverflow.com/a/28065664/4034572
Albert Vila Calvo
Tak, to zadziałało dla mnie. Miałem obrazy o rozmiarze około 1 MB i umieściłem je w mipmap-xxhdpi
3

jeśli używasz Picassa, zmień na Glide w ten sposób.

Usuń Picasso

Picasso.get().load(Uri.parse("url")).into(imageView)

Zmień Glide

Glide.with(context).load("url").into(imageView)

Bardziej wydajny

Deniz
źródło
Nadal pojawia się błąd, nawet po przełączeniu na Glide z Picassa. Na telefonie Samsung J6. I Moto Z2 :(
Rohit Singh
2

Istnieje kilka scenariuszy, w których oryginalna bitmapa musi zostać narysowana w ImageViews, aplikacjach do edycji zdjęć itp.,

Jak wspomniano powyżej ustawienie zatoki

android:hardwareAccelerated="false"

Spowoduje złe doświadczenia z interfejsem użytkownika, możesz ustawić przyspieszenie sprzętowe Tylko jedno wybrane działanie, w którym ma być narysowany obraz w wysokiej rozdzielczości

<application android:hardwareAccelerated="true">
    <activity ... />
    <activity android:hardwareAccelerated="false" />
</application>
Balu mallisetty
źródło
0

Pliki ikon są zbyt duże, aby system Android mógł je wydajnie i płynnie załadować. Android rozpoznaje to dzięki swoim inteligentnym algorytmom.

Możesz zmienić rozmiar plików ikon za pomocą Final Android Resizer przez asystat. Zmień ich rozmiar na „xhdpi” lub niższy.

Umieść zdjęcia o zmienionym rozmiarze do rysowania lub nadpisz na istniejących dużych plikach ikon.

Następnie gotowe.

lloydyu24
źródło
0

jeśli używasz Glide i ładujesz 1k obrazów na raz lub kilka obrazów, to jest to kwestia poślizgu lub czegokolwiek, co robisz, aby ustawić widok obrazu. można go rozwiązać po prostu stosując typ skali w poślizgu.

Deepak Rajput
źródło
0

W moim przypadku właśnie zmieniłem płótno obrazu, które jest używane w tle za pomocą Paint3d (lub możesz użyć dowolnego innego). Tutaj udostępniam zrzut ekranu, po prostu go przejrzyj.

Vishaljoshi007
źródło
Użyj komentarzy, aby podzielić się swoimi przemyśleniami.
Ajay Sivan
0

rozwiązuje się go, zmniejszając rozmiar obrazów.

HosseinRezaie
źródło