Skip to main content

Android Parcelable Example

Few days back I had a requirement to send a ArrayList of my Custom Class Objects through Android Intent, I guess most of you also find this requirement now and then. I never thought it can be that tricky.

There are built in functions in Intent to send ArrayList of primitive objects e.g. String, Integer, but when it comes to Custom Data Handling Objects, BOOM… you need to take that extra pain!

Android has defined a new light weight IPC (Inter Process Communication) data structure called Parcel, where you can flatten your objects in byte stream, same as J2SDK’s Serialization concept.

So let’s come back to my original requirement, I had a Data Handling class, which groups together a set of information-

public class ParcelData {
      int id;
      String name;
      String desc;
      String[] cities = {"suwon", "delhi"};
}

I want an ArrayList<ParcelData> of Data Handling objects to be able to pass through Intent. To do that, I can’t use the ParcelData as it is; you need to implement an Interface android.os.Parcelable which will make Objects of this class Parcelable. So you need to define your data handling class as-

public class ParcelData implements Parcelable {
      int id;
      String name;
      String desc;
      String[] cities = {"suwon", "delhi"};
}

You need to overwrite 2 methods of android.os.Parcelable Interface-

  • describeContents()- define the kind of object you are going to Parcel, you can use the hashCode() here.
  • writeToParcel(Parcel dest, int flags)- actual object serialization/flattening happens here. You need to individually Parcel each element of the object.

public void writeToParcel(Parcel dest, int flags) {
      Log.v(TAG, "writeToParcel..."+ flags);
      dest.writeInt(id);
      dest.writeString(name);
      dest.writeString(desc);
      dest.writeStringArray(cities);
}

Note: Don’t try things like, dest.writeValue(this) to flatten the complete Object at a time (I don’t think all people have some weird imaginations like me, so you’ll never try this, right ?…) that will end up in recursive call of writeToParcel().

Up to this point you are done with the required steps to flatten/serialize your custom object.

Next, you need to add steps to un-marshal/un-flatten/de-serialize (whatever you call it) your custom data objects from Parcel. You need to define one weird variable called CREATOR of type Parcelable.Creator. If you don’t do that, Android framework will throw exception-

Parcelable protocol requires a Parcelable.Creator object called CREATOR

Following is a sample implementation of Parcelable.Creator<ParcelData> interface for my class ParcelData.java

/**
 * It will be required during un-marshaling data stored in a Parcel
 * @author prasanta
 */
public class MyCreator implements Parcelable.Creator<ParcelData> {
      public ParcelData createFromParcel(Parcel source) {
            return new ParcelData(source);
      }
      public ParcelData[] newArray(int size) {
            return new ParcelData[size];
      }
}

You need to define a Constructor in ParcelData.java which puts together all parceled data back

/**
* This will be used only by the MyCreator
* @param source
*/
public ParcelData(Parcel source){
    /*
     * Reconstruct from the Parcel
     */
    Log.v(TAG, "ParcelData(Parcel source): time to put back parcel data");
    id = source.readInt();
    name = source.readString();
    desc = source.readString();
    source.readStringArray(cities);
}

You can deserve some rest now…...as you are done with it. So now you can use, something like

Intent parcelIntent = new Intent(this, ParcelActivity.class);
ArrayList<ParcelData> dataList = new ArrayList<ParcelData>();
/*
 * Add elements in dataLists e.g.
 * ParcelData pd1 = new ParcelData();
 * ParcelData pd2 = new ParcelData();
 *
 * fill in data in pd1 and pd2
 *
 * dataLists.add(pd1);
 * dataLists.add(pd2);
 */
parcelIntent.putParcelableArrayListExtra("custom_data_list", data);

So, how hard is that? :-). Share your comments, I'm listening.

Comments

  1. good example......Thanks
    - santhana

    ReplyDelete
  2. Very well explained....thankyou!! :)

    One more thing wat if I have a Parceable object that has List instanceVariable?

    ReplyDelete
  3. Hi Anandram,
    if that list instance variable contains premitive objects, you don't have to do anything special i.e. probably need to call writeList() to write to parcel.

    But if the parcelable object contains List of Custom objects, you need to make your Custom Class also Parcelable and need to use-
    writeTypedList()

    and
    readList(listInstance, .class.getClassLoader());

    Hope this helps.

    ReplyDelete
  4. Hi really a nice article. Good work. Thank you :)

    ReplyDelete
  5. this is really helpful.. in fact i was very much confused initially.. thanks a lot for posting this wonderful tutorial..

    ReplyDelete
  6. Excellent - i tried to write my parcelable by following the SDK doc, but it was riddled with uncertainty. I followed your technique and had it written in 15 minutes and debugged in 5.

    You might want to include a non-native type like Date and null member data. I had a class similar to yours with an uninitialized date.

    ReplyDelete
  7. Hi Bob,
    appreciate your comments.

    Probably I'll write Part 2 of this which will include a set of advance data structures and your custom classes.

    Let's see when I get time to do that :-)
    Thanks,
    Prasanta

    ReplyDelete
  8. Hi prashant

    i gotta pass an object in intent it is of Messgae[] type(i guess you know this). i did whatever you said and the only change was source.writeArray(Object[] val) where am passing my object of Message[] type. Now, what code to be overwritten on the other side to handle this.Please respond asap

    ReplyDelete
  9. Hi Vivek,
    I guess you are talking about android.os.Message.
    Message internally implements Parcelable, so you need not to worry for its internal data marshaling/un-marshaling.
    If you are using an array of Message[] msgs-
    to write-
    dest.writeArray(msgs);

    to read-
    source.readArray(ParcelData..class.getClassLoader());

    I hope this will work.
    Thanks,
    Prasanta

    ReplyDelete
  10. I'm having trouble recovering the data in the other activity:

    //onCreate
    ArrayList listaCadastradaArray = (ArrayList) getIntent().getParcelableArrayExtra("listaCadastrada");

    it says it can't cast from Parcelable[] to ArrayList

    ReplyDelete
  11. Roger: if you remove the cast your code should work, I had the same problem. I guess you can directly assign the parcelable arraylist to your custom arraylist...

    ReplyDelete
  12. Thanks for sharing, Prasanta!

    Cheers,
    Torsten

    ReplyDelete
  13. Hey Prasanta Paul,

    I appreciate your help.

    Cheers,
    Ritesh

    ReplyDelete
  14. Hi, at first i would like to thank you for your example! At second i have a little problem with recovering the data from intent. Could you please tell me, where is mistake?
    In activity A I do this:
    ArrayList tmpRecordAll = getAllRecords();
    Intent intentAllData = new Intent(DATA_BROADCAST);
    intentAllData.putParcelableArrayListExtra("AllRecordsByID", tmpRecordAll);
    sendBroadcast(intentAllData);
    In actvity B I have this:
    ArrayList tmpArrayListID = intent.getParcelableArrayListExtra("AllRecordsByID");
    and after that the tmpArrayListID is empty...
    thanks for help.

    ReplyDelete
  15. Sorry for my previous comment. Everthing is working fine, error was elsewere :)

    ReplyDelete
  16. I there some method in Parcel so I can write a TreeMap in a Parcel?

    ReplyDelete
  17. How do you handle a nested complex object inside ParcelData i.e. ArrayList where T is a complex object? How would the writeToParcel look?

    ReplyDelete
  18. Where is MyCreator used in the scheme of things?

    ReplyDelete
  19. wow. i like the way you put these tiny puzzle-pieces together with that very simplistic and concise explanation. i have a little query though.

    how would you actually know which string is which? for example, like in your class, you will have multiple similar variables, let's say you have 5 strings..how would you know that this is the 'name' string or this is the 'gender' string..or things like that, when the way to retrieve them is only through the method readString()? would you have to retrieve them in a sequence exactly similar to how you wrote them? this is confusing.

    thats the only little missing piece in this mind-puzzle that i have inside my head about this parcelable interface..

    thank you so much sir. :)

    could anybody help me? ^^

    ReplyDelete
  20. This post - http://idlesun.wordpress.com/2011/07/15/android-parcelable-example-2-sub-object-and-list/ answered my questions. He has an example 1 post out there as well.

    ReplyDelete
  21. Just to echo what Vivek asked, I'm looking to pass a Date. How would I go about doing that?

    ReplyDelete
  22. Excellent example! Thank you!

    ReplyDelete
  23. "static final: must used for CREATOR cariable

    public static final Parcelable.Creator CREATOR=...
    in parceldata.java

    ReplyDelete
  24. thanx a lot Prasanta .. u r an angel :)
    -Ash

    ReplyDelete
  25. Nice One. You helped me at a critical situation

    ReplyDelete
  26. Very useful articular for me
    Thanks a lot
    dharmendra.sahu09@gmail.com

    ReplyDelete
  27. Hi ,
    Is it possible to pass a pointer to structure in binders between proxy and native .

    Regards,
    Raj

    ReplyDelete
  28. Great Job.. thanks!!

    ReplyDelete
  29. Prasanta, thanks for writing this. Very helpful.

    ReplyDelete
  30. Hi Prasantha,
    is it possible for us to pass the socket, inputstream and output stream the same way ? Kindly give a thought in this.
    I've a requirement to pass the bluetooth socket from one activity to the other. But I don't know how to do that. Kindly share some sample code if you have any.

    Thanks
    Sathish

    ReplyDelete
  31. Hi prasantha,

    Is it possible to parcel a date and Map> if possible please let me know

    ReplyDelete
  32. Hi Prasantha,

    This example is really good.

    thanks.

    ReplyDelete
  33. I found this article very useful and hope that it will be very helpful for those who are new to Android.

    Here I would like to ask one question that is it necessary to maintain order while UN-marshaling data i.e, one has to read the data in the same order in which the data has written to the parcel ?

    ReplyDelete
  34. Thanks man! I like the way you explain it and sahre your emotions with us!
    best rgrads from Brazil!

    ReplyDelete
  35. Thanks for sharing this knowledge.

    ReplyDelete
  36. Good Article !!!...Post more dude!!

    ReplyDelete
  37. how to move multiple objects within two activities?

    ReplyDelete
  38. how to move multiple objects within two activities?

    ReplyDelete
  39. Parcelable doesn't seem to work for a little more complicated object, e.g. a Parcelable with recursive call of its ownself, that means a Parcelable has a ListArray of dynamical size inside, e.g:

    public class ParcelData implements Parcelable {
    int id;
    String name;
    String desc;
    String[] cities = {"suwon", "delhi"};

    ListArray mSubItemList;
    }

    and by calling

    private ParcelData( Parcel in ) {
    id = in.readInt();
    name = in.readString();
    desc = in.readString();
    in.readStringArray(cities);

    // now the problem, note: the dim info has already been written into Parcel
    // by using writeToParcel()
    int numberOfSubitems = in.readInt();
    if( numberOfSubitems > 0 ) {
    mSubItemList = new ListArry();
    for( int i = 0; i < numberOfSubitems; i++ ) {
    mSubItemList.add( new ParcelData(in) );
    }
    }
    else {
    mSubItemList = null;
    }
    // it causes exception, where is the problem???
    }


    Steven

    ReplyDelete
  40. Thanks for the code!

    ReplyDelete
  41. Hello,
    I want to get the location reminder whenever we are going to one place to another place when it reach that destination alert dialog is display in background using service.

    ReplyDelete
  42. Hello sir..:)
    Prateek here.
    Nice example.

    ReplyDelete
  43. Thanks!! really great and easy to follow and understand example! really helped in my android uni proj!

    ReplyDelete
  44. Prasanna and other folks who benefited out of this,
    Can you please share the source code as an android project.

    Thanks in advance.

    ReplyDelete
  45. Great job Prasanta !!! Many many thanks !!!

    ReplyDelete
  46. Great job! But I only change

    public static final Parcelable.Creator CREATOR = new Creator() {
    public ParcelData createFromParcel(Parcel source) {
    return new ParcelData(source);
    }
    public ParcelData[] newArray(int size) {
    return new ParcelData[size];
    }
    };

    ReplyDelete
  47. Nice tutorial but why there is no real data placed in to Parcel? How to set data id, name... for each of element in Parcel list?

    ReplyDelete
  48. Nice tutorial! Thank you very much!

    ReplyDelete
  49. Good post... very helpful for beginners like me.
    As already said in one of the replies, I had to change the CREATOR to parcel it successfully.

    ReplyDelete
  50. What about circular references ?I think parcelable does not support circular references

    ReplyDelete
  51. Thanks for the helpful tutorial.

    ReplyDelete

Post a Comment

Popular posts from this blog

Call Control in Android

This tutorial is for those who want to control Phone Call in Android OS. Programmatic approach to Accept or Reject call without user intervention. Kindly note, this approach uses Java Reflection to call methods of an internal class of Android Telephony Framework and might not work with all versions of Android OS. The core concept has been explained in this Android open code . 1st thing 1st, Give the permission . You need to define 3 User Permissions to handle call related functionality- android.permission.READ_PHONE_STATE android.permission.MODIFY_PHONE_STATE (For answerRingingCall() method) android.permission.CALL_PHONE (For endCall() method) Define a Receiver... Create a Receiver which accepts broadcasts with intent action android.intent.action.PHONE_STATE, define following in the Manifest- [receiver android:name=".PhoneCall"]         [intent-filter]             [action android:name="android.intent.action.PHONE_STATE"/]            [/intent-filter] [/receiver] Ha

Android Looper and Toast from WorkerThread

Have you ever tried to launch Android Toast message from worker thread? Probably you are wondering why the heck it is giving this error- java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare() In this article we are going to explore reason behind the above exception and try to understand how Looper works in Android. At the end, I am going to explain one approach to run Toast from a worker thread, but before that we need to understand how Looper works. If you already know in/out of Looper, you can skip below section and directly move to the solution part. Looper is a very basic wrapper class which attach a MessageQueue to a Thread and manage this queue. MessageQueue is a structure to sequentialize simultaneous processing requests of a Thread.  In Android, message/request processing classes like Handler uses Looper to manage their respective MessageQueue. Looper = Thread + MessageQueue Android Looper Life Cycle: As you can see in the abo

Overlay on Android Layout

This will help you to create custom Layout and add Overlay on a LinearLayout. The concept can be reused on other Layout classes i.e. RelativeLayout, FrameLayout etc. I have added a popup Selection Palette, containing "Map Pin" and "List" icons. You can minimize the popup by clicking on the section in Green on the left side bottom corner of the screen.   How can I do that- You need to follow 4 steps- 1. Override LinearLayout Create a Class MyLinearLayout.java which should overwrite LinearLayout 2. Drawing You need to overwrite dispatchDraw (Canvas canvas) method. It gives control to the whole screen. Make sure you set android:layout_height="fill_parent" for the associated layout definition in XML. You can draw anything and anywhere on the canvas. dispatchDraw (Canvas canvas) gets called only after underlying views are drawn, so whatever you draw comes in the foreground.   3. Event Handling You need to overwrite dispatchTouchEvent (MotionEvent e

Android Custom TextView

Have you ever tried to add custom behavior to in-build Android Text View or create custom attributes? If yes, this article is going to help you. Here we'll create Single Custom TextView with support for custom attributes to display First and Last Name in different font and colors. During this process we'll learn following topics- 1. How to override default Views in Android 2. How to define custom Layout Attributes in Android So, Let's get started... Following sections explains necessary changes required in Java code and XML layout files. Create Custom Text View (MyTextView.java) 1. Override Android's default TextView   2. Implement Constructors. If you want custom attributes, override Constructor having Attributes in argument. 3. Override onMeasure(): Calculate required width and height, based on Text Size and selected Font. Once calculation is complete, set updated measure using setMeasuredDimension (reqWidth, reqHeight) Note: It’s really important to define the corr

Google SpreadSheet Library for Android

You might have already tried using Google's GData Lib to access SpreadSheet from Android, and after few hours of try, you start Google for any alternate solution. I have also spent number of hours without any solution. So, I have developed SpreadSheet client Lib [ works on Android :-) ] and ideally work on any Java platform- http://code.google.com/p/google-spreadsheet-lib-android/ Latest version: 2.1 (Added support for List Feed. Please visit above link to get more info.) Supported Features: 1. Create/Delete Spreadsheet 2. List all stored Spreadsheets 3. Add/Delete WorkSheet into/from a given SpreadSheet 4. List all Worksheets of a given Spreadsheet 5. Add Records into WorkSheet/SpreadSheet (It supports Table based record handling) 6. Retrieve Record from WorkSheet/SpreadSheet ( Structured Query support) 7. Retrieve Record as List Feed from Worksheet 8. Update/Delete Records 9. Share ShreadSheet with user/group/domain. 10. Conditional data retrieval-

Android Fragment

Fragment is being hanging out since Andriod 3.0, but with the release of 4.0, it has become an obvious choice for Android Application development for both Tabs and Smart phones. Few people think, fragment is a " Superman " which can add any kind of UI layout/style/decoration. But that is not true, rather than being an UI layout or decoration enhancer, Fragment is a very important concept to manage segments of your UI component code base . Prior to Fragment, developers were able manage UI flow only at the Activity level. All UI components were Views (mentioned in XML layout and part of Activity) and there was no way to manage these components separately. As a result all view management code were in a single file i.e. Activity class. With fragment approach, we can now remove View management code from Activity and place them in their respective Java classes. So, a pretty neat approach for code management. Here I'll explain various concepts of Fragment with an example appli

HashMap Internal

I always wanted to implement the logic behind the famous data structure of Java , HashMap and here it comes. Though it’s not the complete implementation considering all optimization scenarios, but it will highlight the basic algorithm behind the HashMap . So let’s start, this implementation will use my LinkedList implementation (Reason: for this implementation I thought to write everything from the scratch apart from primitive data types. Sounds weird? May be ;-) ). You may refer my earlier post on LinkedList , as I’m going to use it. HashMap is a key-value pair data structure, where you retrieve value by passing key. To optimize the search of key, a concept of Bucket (an Array of Java Objects) has been introduced. This is used, so that if search hits this Bucket , corresponding value element is instantly retrieved, otherwise it iterates sequentially through the Linked List associated with each Bucket element. So you can say if all HashMap elements get fit into the Bucket, retrieving

Accessing Yahoo Finance API

Since last few days I was wondering the right set of Web Service to read Country wise Stock Exchange index information . I found a bunch of scattered information, but no straight forward answer. It seems there are not many "reliable" and "flexible" options and Yahoo Finance is one of the top of this class. Though Yahoo Finance is very powerful, some how its very less documented and it seems Yahoo doesn't care much about this wonderful web service and expect Developers to do some kind of "hacking". The only online resource that I (and most of you as well ) found is one 3rd party web site- http://www.gummy-stuff.org/Yahoo-data.htm and it seems they know much more than what Yahoo dose..;-) Anyway let me continue and share my experience and information to help budding developer who wants to use Yahoo Finance Web Service in their Mobile, Web o r Desktop s olution. There are 2 set of APIs to access Yahoo Finance details- YQL based Web Service : Th

Eclipse EGIT, Download Code, Attach Framework code & Debug

This article explains procedure to download Android source (few important Apps and Framework base code) using Eclipse EGit plugin and then attach framework code to debug important framework classes (e.g. Activity etc.). Install EGit Download Source from GIT Repository Attach Framework code Debug Download EGit Plug-in EGit is a GIT plugin for Eclipse which helps to mange GIT clone, Check-ins, Sync etc. from your Eclipse workspace. Eclipse (Version: 3.7.x) -> Help -> Install New Software -> "Add" - " http://download.eclipse.org/egit/updates ". Once the plug-in installation is successful, you'll find a new Eclipse View perspective- "Git Repository Exploring"    Download Android source To download code from Android GIT repository, we need to create "local Git clone". Each local clone is associated with Remote Clone URL.   https://android.googlesource.com/ lists Git Repository URLs for different sections of An