How to do Android IPC with Parcelable and AIDLs.

This tutorial describes how to create your own Parcelable implementation and how to do IPC between an activity and service.

1. Understanding Parcelable in Android

1.1. Using Bundle to pass data between Android components

The Bundle object which is used to pass data to Android components is a key/value store for specialized objects. It is similar to a Map but can only contain these specialized objects

You can place the following objects types into a Bundle:

  • String

  • primitives

  • Serializable

  • Parcelable

If you need to pass your customer objects via a Bundle, you should implement the Parcelable interface.

1.2. Implementing Parcelable

A Parcelable is the Android implementation of the Java Serializable. It assumes a certain structure and way of processing it. This way a Parcelable can be processed relatively fast, compared to the standard Java serialization.

To allow your custom object to be parsed to another component they need to implement the android.os.Parcelable interface. It must also provide a static final method called CREATOR which must implement the Parcelable.Creator interface.

package com.vogella.android.autovalueparceable;

import android.os.Parcel;
import android.os.Parcelable;

public class Student implements Parcelable {

    public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
        public Student createFromParcel(Parcel in) {
            return new Student(in);
        }

        public Student[] newArray(int size) {
            return new Student[size];
        }
    };

    private long id;
    private String name;
    private String grade;

    // Constructor
    public Student(long id, String name, String grade){
        this.id = id;
        this.name = name;
        this.grade = grade;
    }

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getGrade() {
        return grade;
    }

    public void setGrade(String grade) {
        this.grade = grade;
    }

    // Parcelling part
       public Student(Parcel in){
           this.id = in.readLong();
           this.name = in.readString();
           this.grade =  in.readString();
       }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
       public void writeToParcel(Parcel dest, int flags) {
        dest.writeLong(this.id);
        dest.writeString(this.name);
        dest.writeString(this.grade);
       }

    @Override
    public String toString() {
        return "Student{" +
                "id='" + id + '\'' +
                ", name='" + name + '\'' +
                ", grade='" + grade + '\'' +
                '}';
    }
}

Once you have defined this, you can put it into the extra of an intent.

intent.putExtra("student", new Student("1","Mike","6"));

To access the parcel on the other side, you can use the following example code.

Bundle data = getIntent().getExtras();
Student student = (Student) data.getParcelable("student");

2. Using Auto-Value to generate Parcelable implementations

Writing `Parcelable`s is time-consuming and error-prone process. AutoValue and its extensions allow you to generate such classes automatically.