Fehlgeschlagene Binder-Transaktion beim dynamischen Einfügen einer Bitmap in ein Widget

116

Kann mir jemand den Grund für einen fehlgeschlagenen Binder-Transaktionsfehler nennen ? Ich kann diese Fehlermeldung in logcat sehen. Ich erhalte diesen Fehler, wenn ich versuche, eine Bitmap dynamisch in ein Widget einzufügen ...

Eby
quelle

Antworten:

91

Dies liegt daran, dass alle Änderungen an den RemoteViews serialisiert werden (z. B. setInt und setImageViewBitmap). Die Bitmaps werden auch in ein internes Bundle serialisiert. Leider hat dieses Bundle eine sehr kleine Größenbeschränkung.

Sie können das Problem lösen, indem Sie die Bildgröße folgendermaßen verkleinern:

 public static Bitmap scaleDownBitmap(Bitmap photo, int newHeight, Context context) {

 final float densityMultiplier = context.getResources().getDisplayMetrics().density;        

 int h= (int) (newHeight*densityMultiplier);
 int w= (int) (h * photo.getWidth()/((double) photo.getHeight()));

 photo=Bitmap.createScaledBitmap(photo, w, h, true);

 return photo;
 }

Wählen Sie newHeight, um klein genug zu sein (~ 100 für jedes Quadrat, das auf dem Bildschirm angezeigt werden soll), und verwenden Sie es für Ihr Widget, damit Ihr Problem gelöst wird :)

GalDude33
quelle
1
Was ich nicht ganz verstehe, ist, was genau hier passiert. Ich verwende einen ViewPager mit einem ziemlich großen Datensatz, der sich jedoch trotz des Spam-Fehlers im Ordner an alles zwischen den Seiten erinnert. Wird das Bundle in den lokalen Speicher geschrieben und dann vorab abgerufen oder was? Kann ich möglicherweise Daten verlieren, wenn ich weitere Seiten hinzufüge?
G_V
6
Dies verringert jedoch die Bildqualität
John Joe,
64

Sie können die Bitmap als Byte-Array komprimieren und dann in einer anderen Aktivität wie dieser dekomprimieren.

Kompresse!!

        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        bmp.compress(Bitmap.CompressFormat.PNG, 100, stream);
        byte[] bytes = stream.toByteArray(); 
        setresult.putExtra("BMP",bytes);

Dekomprimieren !!

        byte[] bytes = data.getByteArrayExtra("BMP");
        Bitmap bmp = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
Nicolás Loaiza
quelle
1
Perfekt, dies reduziert die Bitmap-Größe erheblich.
Navin
1
Warum nicht JPEG anstelle von PNG verwenden? ist es nicht besser komprimiert?
mehmet6parmak
3
@ mehmet6parmak PNG wird verwendet, weil es im Gegensatz zu JPEG verlustfrei ist. Ja, JPEG wird besser komprimiert, aber die Qualität leidet (etwas) darunter.
Petzku
funktioniert nicht für mich :( stackoverflow.com/questions/34540819/…
John Joe
Ein großes Lob! Tolle Problemumgehung für eine temporäre Implementierung, an der ich gearbeitet habe. Obwohl das Übergeben schwerer Daten bei der Verwendung von Bundles / Intents vermieden werden sollte.
Sud007
37

Der Binder-Transaktionspuffer hat eine begrenzte feste Größe, derzeit 1 MB, die von allen für den Prozess laufenden Transaktionen gemeinsam genutzt wird. Folglich kann diese Ausnahme ausgelöst werden, wenn viele Transaktionen ausgeführt werden, selbst wenn die meisten einzelnen Transaktionen von mäßiger Größe sind.

Verweisen Sie auf diesen Link

Dharam
quelle
12

Siehe meine Antwort in diesem Thread.

intent.putExtra("Some string",very_large_obj_for_binder_buffer);

Sie überschreiten den Binder-Transaktionspuffer, indem Sie große Elemente von einer Aktivität zu einer anderen Aktivität übertragen.

Balaji Dubey
quelle
Ich hatte das gleiche Problem, ich entferne nur putExtra Problem sortiert!
Ivor
8

Ich habe dieses Problem gelöst, indem ich Bilder im internen Speicher gespeichert und dann .setImageURI () anstelle von .setBitmap () verwendet habe.

MartinC
quelle
1
und die Bilder nicht von Bildschirm zu Bildschirm durch Parcelable leiten oder so, ich denke, das ist in diesem Fall am schlimmsten
MartinC
3

Der richtige Ansatz besteht darin, jedes Mal, wenn Sie die Benachrichtigung aktualisieren, setImageViewUri()(langsamer) oder das setImageViewBitmap()und neu zu RemoteViewerstellen.

Alexander Woodblock
quelle