Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Class Cast Exception when passing array of Serializables from one activity to another

I have an array containing serializable objects and am trying to use Intent's putExtra() and Bundle's getSerializable(). However, I am getting a class cast exception and don't understand why.

Below is the code. UserInfo is my own class which implements Serializable, and I have been able to pass individual UserInfo objects between activities. I've only ran into this problem when attempting to use an array.

Code sending the serializable:

Intent intent = new Intent( JOIN_GROUP ); //JOIN_GROUP is a constant string

String user_ids[] = packet.userIDs();

int length = user_ids.length;
UserInfo users[] = new UserInfo[length];

for ( int i = 0; i < length; ++i )
    users[i] = getUserByID( user_ids[i] );

intent.putExtra( USERS_IN_GROUP, users );

Code retrieving the serializable:

Bundle extra = intent.getExtras();          
String action = intent.getAction();

if ( action.equals(IMService.JOIN_GROUP) )
{   
    //CLASS CAST EXCEPTION
    UserInfo users[] = (UserInfo[]) extra.getSerializable( IMService.USERS_IN_GROUP ); 
}

Here is the error:

enter image description here

Question

I'm aware I could probably just use a different data structure, but I would like to understand why the array does not work since arrays are serializable?

EDIT: SnyersK was able to get a simpler but similar scenario to work. So I tried the same thing, and I still get the same exception. It turned my array of Tests into an Object when retrieving the array, which results in the casting exception.

My Test object:

package types;

import java.io.Serializable;

public class Test implements Serializable {

    private static final long serialVersionUID = 1L;

    private String hello = "hello";

}

Code to pass the array of Test objects:

Test myArray[] = new Test[] { new Test(), new Test() };
Intent i = new Intent( this, Login.class );
i.putExtra( "key", myArray );

Code to retrieve the array of Test objects:

Bundle extras = getIntent().getExtras();
Test array[] = (Test[]) extras.getSerializable( "key" ); //Class Cast Exception
like image 203
Kacy Avatar asked Feb 25 '15 13:02

Kacy


1 Answers

Apparently this is a bug on older versions of Android. (Version 5.0.1 is the only version tested on which it works like expected, perhaps it works from 5.0 and up)

The bug

Let's say we have an Array of an object called User which implements Serializable.

User[] users;

When we try to pass this array to another activity through an intent like this

intent.putExtra("myKey", users);

our users will get converted to Object[].

If we try to get our array from the intent in the second activity like so

User[] users = getIntent().getSerializableExtra("myKey");

We will get a ClassCastException.

From the docs, we can conclude that this shouldn't be a problem since Array is a serializable class, and putExtra(String key, Serializable value) has been added since api 1.

If you want to pass an Array through an intent on Android versions prior to Android 5.0.1 (maybe some older versions work aswell, but up to Android 4.3 it is NOT working) You'll have to work around it. You could do this by converting your Array to an ArrayList.

EDIT

another workaround is copying your extra to a new array, thus, not having to cast it. I'm not sure about the positive/negative consequences of the method though. It would look like this:

Object[] array = (Object[]) getIntent().getSerializableExtra("key");
User[] parsedArray = Arrays.copyOf(array, array.length, User[].class);

I found this method here: How to convert object array to string array in Java.

like image 199
SnyersK Avatar answered Oct 04 '22 00:10

SnyersK