Issue
BACKGROUND
Hello all. I am making an app which has a main activity with a list of custom objects. Each item shows a picture, a title and a subtitle, all taken from the item's object attributes.
On the first version of the app, when an item was clicked, the object was sent as Parcelable
with an Intent
to another activity, which showed all the attributes the object has, including the image. At that time, the attribute of the image was only the Resources
ID of the image, so I only had to load the image with that ID.
On my current version, I added a new activity which allows the user to set the object information in order to add the new object to the main activity list. However, the user selects the image from the gallery. In order to face that, I changed the initial ID attribute to Drawable
, so I could assign directly both the Resources
pictures and the Gallery picked ones.
That gave me a FAILED BINDER TRANSACTION
error, so I decided to save the images as byte[]
in order to avoid that.
CURRENT SITUATION AND PROBLEM
My custom object constructor gets the Drawable
and uses the following method to convert it to byte[]
:
private byte[] drawableToBytes(Drawable img)
{
ByteArrayOutputStream stream = new ByteArrayOutputStream();
((BitmapDrawable)img).getBitmap().compress(Bitmap.CompressFormat.PNG, 50, stream);
return stream.toByteArray();
}
In order to get the object from Parcelable
, I use the following method:
public CentroMando(Parcel in)
{
String[] datos = new String[11];
in.readStringArray(datos);
this.setAbreviatura(datos[0]);
this.setNombre(datos[1]);
this.setImagenBytes(Base64.decode(datos[2], Base64.DEFAULT)); // <----- Image
this.setLugar(new Lugar(datos[3],
Double.parseDouble(datos[4]),
Double.parseDouble(datos[5]),
Double.parseDouble(datos[6])));
this.setComandante(datos[7]);
this.setEnlaceCentroMando(datos[8]);
this.setEnlaceLocalizacion(datos[9]);
this.setEnlaceComandante(datos[10]);
}
To convert the object to Parcelable
:
public void writeToParcel(Parcel dest, int flags)
{
dest.writeStringArray(new String[]
{
this.getAbreviatura(),
this.getNombre(),
Base64.encodeToString(this.getImagenBytes(), Base64.DEFAULT), // <----- Image
this.getLugar().getNombre(),
String.valueOf(this.getLugar().getLatitud()),
String.valueOf(this.getLugar().getLongitud()),
String.valueOf(this.getLugar().getDireccion()),
this.getComandante(),
this.getEnlaceCentroMando(),
this.getEnlaceLocalizacion(),
this.getEnlaceComandante()
});
}
To get the Drawable
from the byte[]
, I use the following:
public Drawable getImagenBytesDrawable()
{
byte[] datosBitmap = this.getImagenBytes();
Bitmap imagenBitmap = BitmapFactory.decodeByteArray(datosBitmap, 0, datosBitmap.length);
return new BitmapDrawable(imagenBitmap);
}
Now, when I click on the items in the ListView
, some load without any problems and showing the image and properties fine, but the rest of them close the app without any error on Logcat. I had to remove filters in Logcat to actually find the problem:
2019-11-14 01:33:18.287 2110-14522/? E/ActivityManager: Transaction too large, intent: Intent { cmp=com.example.ud4_propuesto_1/.DatosCentroMandoActivity (has extras) }, extras size: 594808, icicle size: 0
2019-11-14 01:33:18.287 2110-14522/? D/GamePkgDataHelper: notifyAppCreate(), pkgName: com.example.ud4_propuesto_1, sendRet: true
2019-11-14 01:33:18.287 2110-12153/? D/GamePkgDataHelper: getGamePkgData(). com.example.ud4_propuesto_1
2019-11-14 01:33:18.287 2110-12153/? D/GameManagerService: handleMessage(), MSG_APP_CREATE. ignore. pkgName: com.example.ud4_propuesto_1
2019-11-14 01:33:18.289 2110-14522/? E/JavaBinder: !!! FAILED BINDER TRANSACTION !!! (parcel size = 598680)
2019-11-14 01:33:18.289 2110-14522/? E/ActivityManager: Second failure launching com.example.ud4_propuesto_1/.DatosCentroMandoActivity, giving up
android.os.TransactionTooLargeException: data parcel size 598680 bytes
at android.os.BinderProxy.transactNative(Native Method)
at android.os.BinderProxy.transact(Binder.java:1145)
at android.app.IApplicationThread$Stub$Proxy.scheduleTransaction(IApplicationThread.java:1897)
at android.app.servertransaction.ClientTransaction.schedule(ClientTransaction.java:129)
at com.android.server.am.ClientLifecycleManager.scheduleTransaction(ClientLifecycleManager.java:47)
at com.android.server.am.ActivityStackSupervisor.realStartActivityLocked(ActivityStackSupervisor.java:1862)
at com.android.server.am.ActivityStackSupervisor.attachApplicationLocked(ActivityStackSupervisor.java:1199)
at com.android.server.am.ActivityManagerService.attachApplicationLocked(ActivityManagerService.java:10029)
at com.android.server.am.ActivityManagerService.attachApplication(ActivityManagerService.java:10097)
at android.app.IActivityManager$Stub.onTransact(IActivityManager.java:170)
at com.android.server.am.ActivityManagerService.onTransact(ActivityManagerService.java:4162)
at android.os.Binder.execTransact(Binder.java:739)
2019-11-14 01:33:18.290 2110-14522/? I/ActivityManager: Process com.example.ud4_propuesto_1 (pid 25813) has died: fore TOP (214,2655)
ADITIONAL INFORMATION
I save the Drawable
images as xxxhdpi
.
The items' images that make the app crash weight 410 KB, 393 KB and 393 KB. The rest of the images weight less than 345 KB.
I tested that only the items with those heavier images are the ones that make the app crash.
QUESTION
Is there any way to solve this?
Solution
Intent is limited to 1MB total so sending bitmaps inside it just won't work.
You should have your data object accept either image picked from presets (drawable res) or from gallery (url to cached file?), then resolve it and load image accordingly.
Answered By - Pawel
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.