Échec de la transaction de liant lors de la mise en place dynamique d'un bitmap dans un widget

116

Quelqu'un peut-il me dire la raison de l' échec de l' erreur de transaction de liant ? Je peux voir ce message d'erreur dans logcat. J'obtiens cette erreur en essayant de mettre un bitmap dynamiquement dans un widget ...

Eby
la source

Réponses:

91

Cela est dû au fait que toutes les modifications apportées aux RemoteViews sont sérialisées (par exemple, setInt et setImageViewBitmap). Les bitmaps sont également sérialisés dans un bundle interne. Malheureusement, cet ensemble a une limite de taille très petite.

Vous pouvez le résoudre en réduisant la taille de l'image de cette façon:

 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;
 }

Choisissez newHeight pour être assez petit (~ 100 pour chaque carré qu'il devrait prendre à l'écran) et utilisez-le pour votre widget, et votre problème sera résolu :)

GalDude33
la source
1
Ce que je ne comprends pas très bien, c'est ce qui se passe ici exactement. J'utilise un ViewPager avec un ensemble de données assez volumineux, mais il se souvient de tout entre les pages malgré le spam d'erreur du classeur. Le bundle est-il écrit sur le stockage local, puis pré-extrait ou quoi? Puis-je éventuellement perdre des données si j'ajoute plus de pages?
G_V
7
Mais cela réduira la qualité de l'image
John Joe
64

Vous pouvez compresser le bitmap en tant que tableau d'octets, puis le décompresser dans une autre activité, comme celle-ci.

Compresse!!

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

Décompressez !!

        byte[] bytes = data.getByteArrayExtra("BMP");
        Bitmap bmp = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
Nicolás Loaiza
la source
1
Parfait, cela réduit considérablement la taille du bitmap.
Navin
1
pourquoi ne pas utiliser JPEG au lieu de PNG? n'est-ce pas mieux compressé?
mehmet6parmak
3
@ mehmet6parmak PNG est utilisé car il est sans perte, contrairement au JPEG. Oui, JPEG compresse mieux, mais la qualité en souffre (un peu).
Petzku
ne fonctionne pas pour moi :( stackoverflow.com/questions/34540819/…
John Joe
Gloire! Excellente solution de contournement pour une implémentation temporaire sur laquelle je travaillais. Bien que la transmission de données lourdes soit évitée lors de l'utilisation de Bundles / Intents.
sud007
37

Le tampon de transaction Binder a une taille fixe limitée, actuellement 1 Mo, qui est partagée par toutes les transactions en cours pour le processus. Par conséquent, cette exception peut être levée lorsque de nombreuses transactions sont en cours, même lorsque la plupart des transactions individuelles sont de taille moyenne.

renvoyer ce lien

Dharam
la source
12

Voir ma réponse dans ce fil.

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

Vous dépassez le tampon de transactions du classeur en transférant des éléments volumineux d'une activité à une autre activité.

Balaji Dubey
la source
J'ai eu le même problème que je viens de supprimer le problème putExtra trié!
Ivor
8

J'ai résolu ce problème en stockant des images sur le stockage interne, puis en utilisant .setImageURI () plutôt que .setBitmap ().

MartinC
la source
1
et ne passez pas les images à travers Parcelable d'un écran à l'autre ou plus, je suppose que c'est le pire dans ce cas
MartinC
3

La bonne approche consiste à utiliser setImageViewUri()(plus lentement) ou à setImageViewBitmap()recréer RemoteViews chaque fois que vous mettez à jour la notification.

Gravure sur bois Alexander
la source