"Canvas: Versuch, eine zu große Bitmap zu zeichnen", wenn die Android N-Anzeigegröße größer als "Klein" eingestellt ist

81

Ich habe eine veröffentlichte App, die beim Start auf Android N abstürzt, wenn die neu eingeführte Display sizeBetriebssystemeinstellung auf einen zu großen Wert eingestellt ist.

Wenn ich in logcat nachschaue, wird folgende Meldung angezeigt:

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

Ich habe das Problem in meiner ersten Aktivität auf eine ImageView zurückgeführt, die ein schönes großes Hintergrundbild zeigt. Das betreffende Bild ist 2048 x 1066 und befindet sich in meinem generischen drawablesVerzeichnis. Unabhängig von der Dichte wird dieses Bild verwendet.

Alles funktioniert in Ordnung, wenn die Display sizeEinstellung ist Small. Aber wenn ich nach oben gehe Default, funktioniert es nicht mehr. Wenn ich dann das Bild gegen ein kleineres austausche, funktioniert es bei Default, aber wenn ich zu gehe Large, funktioniert es nicht mehr.

Ich vermute, dass Display sizesich Ihr Gerät beim Anpassen wie ein physisch kleineres Gerät mit einer höheren Pixeldichte verhält. Aber ich verstehe nicht, was ich hier machen soll. Wenn ich immer kleinere Bilder für immer höhere Auflösungen einsetze, sieht es auf wirklich großen Displays nicht gut aus. Oder verstehe ich etwas nicht?

Alle Hinweise wäre sehr dankbar.

Brian Rak
quelle
23
"Das fragliche Bild hat eine Größe von 2048 x 1066 und befindet sich in meinem allgemeinen Zeichenverzeichnis. Unabhängig von der Dichte wird dieses Bild verwendet" - res/drawable/ist ein Synonym für res/drawable-mdpi/. Wenn Sie möchten, dass das Bild nicht basierend auf der Dichte skaliert wird, verwenden Sie res/drawable-nodpi/oderres/drawable-anydpi/ .
CommonsWare
3
"Wollen Sie damit sagen, dass ein 100 x 100 Pixel großes Bild, das sich in verschiedenen Ressourcenverzeichnissen befindet, tatsächlich skaliert wird, um eine virtuelle Version mit unterschiedlicher Auflösung zu erstellen, bevor Sie mit dem Layout fortfahren?" - Das hängt davon ab, welche Dichte Sie haben und auf welchem ​​Gerät Sie arbeiten. Wenn es eine genaue Übereinstimmung gibt, wird nichts erneut abgetastet. Wenn keine genaue Übereinstimmung vorliegt, wird das Bild einer nahe gelegenen Dichte erneut abgetastet. Wenn Sie also nur res/drawable/foo.png(auch bekannt als res/drawable-mdpi/foo.png) haben und Ihr Gerät ist xhdpi, wird das Bild entlang beider Achsen verdoppelt, was den vierfachen Speicherplatz beansprucht.
CommonsWare
4
Der 106975232-Wert in Ihrem Fehler beträgt genau das 49-fache der Bildauflösung, was eine 7-fache Neuabtastung entlang beider Achsen bedeutet. Das ist viel höher als ich erwartet hätte. Ich hatte noch keine Gelegenheit, mit den Einstellungen für die Anzeigegröße in Android 7.0
herumzuspielen
6
Schöner Fang auf dem 49x! Ich denke, ich kann erklären, warum es so hoch ist. Beachten Sie, dass diese Zahl Bytes ist. Dieses Bild ist 24-Bit, wird aber wahrscheinlich mit 32 Bit pro Pixel eingelesen. Das würde es 8732672 Bytes im Speicher machen, was genau 12,25 Mal in diese Zahl geht, was wiederum eine 3,5-fache Skalierung entlang jeder Achse impliziert. Dieses Gerät ist xxhdpi, das scheint also ungefähr richtig zu sein. Auf jeden Fall hatte ich keine Ahnung, dass die Ressourcen so neu abgetastet werden würden. Danke für die Hilfe! (Übrigens, das Verschieben des Bildes auf Drawable-Nodpi behebt es tatsächlich.)
Brian Rak
1
Sie sollten wirklich Johans Antwort akzeptieren
S. Jacob Powell

Antworten:

166

In meinem Fall war es die Lösung , die ( hochauflösende ) Splash-Bitmap von drawable nach drawable-xxhdpi zu verschieben .

Ich hatte das gleiche Problem. Ich habe nicht mein Begrüßungsbildschirm vermuten , dass das Problem sein, da es wird angezeigt , wenn die Anwendung gestartet wird, aber es stellte sich heraus , das Splash - Screen ist das Problem.

Der Begrüßungsbildschirm hat in meinem Fall eine Auflösung von xxhdpi und wurde fälschlicherweise im Zeichenordner anstelle von drawable-xxhdpi abgelegt . Dies ließ Android davon ausgehen, dass der Begrüßungsbildschirm eine MDPI-Auflösung hatte, und skalierte das Bild auf das 3 * 3-fache der erforderlichen Größe und versuchte, eine Bitmap zu erstellen.

Johan Franzén
quelle
Ich vermute: Also, Android skaliert ein Bild von xxhdpi auf hdpi, um zum Beispiel ein helleres Bild zu sein? wie du gesagt hast von 3 * 3 -> 1/1 bis 1/3 zum Beispiel?
Ninja Coding
Wie Kalsara Magamage feststellt, ist dies jetzt mipmap-xxhdpi.
Dana Robinson
35

Ich habe das Problem gelöst, nachdem ich den folgenden Code in das Anwendungs-Tag der Manifest-Datei zwischen android: lines eingefügt habe .

android:hardwareAccelerated="false"
CHAMCHOUN
quelle
3
Nun, nach einigen Stunden funktioniert diese Lösung für mobile Probleme mit Xiaomi und Samsung.
Shihab Uddin
3
Dies führt dazu, dass alle Ansichten von CardView deaktiviert werden. Die richtige Lösung wäre also, die Bitmap auf eine kleinere Größe zu skalieren.
Sachin Soma
Anstatt die Hardwarebeschleunigung auf Anwendungsebene zu deaktivieren, ist die Steuerung in Aktivität, Fenster und Ansichtsebene nützlicher.
Mukhammadsher
Aber es gibt noch ein anderes Problem, das danach auftaucht android:hardwareAccelerated="false" . zeigt eine seltsame Ansicht in einem Gerät, dessen API-Level unter 22 liegt.
Prince Dholakiya
Tun Sie das nicht, es verlangsamt Ihre App.
Curio
11

Ich weiß nicht, ob es jemandem helfen würde, aber ich lasse es einfach hier. In meinem Fall - Problem war nur auf Sumsung-Geräten mit Android 7, und Problem war in Splash-Screen-Proportionen. nach dem Ändern der Höhe auf 1024 px - alles funktioniert gut

Kazimad
quelle
Mein Problem war die Bitmap (jpg, png) im zeichnbaren Ordner (ohne Suffix). Es ist meine Dummheit, aber vielleicht hilft es jemandem :-)
Gingo
Das ist hilfreich! Gleiches Problem nur Samsung ... Was hatten Sie zuerst und wie haben Sie es behoben?
M'hamed
Haben Sie versucht, die Bilder von der URL zu laden? Ich habe das gleiche Problem nur mit Samsung Galaxy S6 unter Android 7. Ich lade Bilder in RecyclerView. Ich kann das immer noch nicht herausfinden. @ M'hamed
Rohit Singh
9

Verschieben Sie Ihr Bild im Drawable nach mipmap-xxhdpi. Ihr Bild ist im Bitmap-Format, daher sollten Sie Ihr Bild in den Mipmap-Ordner legen, damit es funktioniert

Kalsara Magamage
quelle
1
AFAIK Der Mipmap-Ordner ist nur für Launcher-Symbole. Ich habe es nie für etwas anderes benutzt. Siehe stackoverflow.com/a/28065664/4034572
Albert Vila Calvo
Ja, das hat bei mir funktioniert. Ich hatte Bildgrößen von ca. 1 MB und habe sie in mipmap-xxhdpi
3

Wenn Sie Picasso verwenden, wechseln Sie wie folgt zu Glide.

Picasso entfernen

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

Glide ändern

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

Effizienter

Deniz
quelle
Ich erhalte immer noch den Fehler, selbst nachdem ich von Picasso zu Glide gewechselt bin. Auf dem Samsung J6-Handy. Und Moto Z2 :(
Rohit Singh
1

Es gibt einige Szenarien, in denen Original-Bitmap in ImageViews, Fotobearbeitungs-Apps usw. gezeichnet werden muss.

als oben erwähnte Bucht Einstellung

android:hardwareAccelerated="false"

Verursacht schlechte UI-Erfahrung. Sie können hardwareAccelerated festlegen. Nur eine ausgewählte Aktivität, bei der hochauflösende Bilder gezeichnet werden sollen

<application android:hardwareAccelerated="true">
    <activity ... />
    <activity android:hardwareAccelerated="false" />
</application>
Balu Mallisetty
quelle
1

Ich habe den Logcat überprüft

Prozess: co.coolresume, PID: 11145 java.lang.RuntimeException: Canvas: Es wird versucht, eine zu große Bitmap (572166144 Byte) zu zeichnen. at android.view.DisplayListCanvas.throwIfCannotDraw (DisplayListCanvas.java:229) at android.view.RecordingCanvas.drawBitmap (RecordingCanvas.java:97) at android.graphics.drawable.BitmapDrawable.draw (BitmapDrawable) widget.ImageView.onDraw (ImageView.java:1367) unter android.view.View.draw (View.java:19380)

Ich habe den Fehler mit dem nächsten Manifest behoben

 <application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme"
    android:hardwareAccelerated="false">
    <activity android:name=".MainActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>
Jose Antonio
quelle
0

Die Symboldateien sind zu groß, als dass Android sie effizient und reibungslos laden könnte. Android erkennt dies an seinen intelligenten Algorithmen.

Sie können die Größe der Symboldateien mit Final Android Resizer ändern von asystat ändern. Ändern Sie die Größe auf "xhdpi" oder niedriger.

Platzieren Sie die Fotos in der Größe in Zeichenform oder überschreiben Sie sie über den vorhandenen großen Symboldateien.

Dann bist du fertig.

lloydyu24
quelle
0

Wenn Sie Gleiten verwenden und jeweils 1k Bilder oder einige Bilder laden, liegt ein Problem mit Gleiten vor oder was auch immer Sie tun, um die Bildansicht festzulegen. Sie können es einfach beheben, indem Sie den Skalentyp in gleiten anwenden.

Deepak Rajput
quelle
0

Dies wird gelöst, indem die Größe der Bilder auf eine niedrigere Größe geändert wird.

HosseinRezaie
quelle