Using self-defined Parcelable objects during an Android AIDL RPC / IPC call

Using self-defined Parcelable objects during an Android AIDL RPC / IPC call

In my previous post “Using the Android Interface Definition Language (AIDL) to make a Remote Procedure Call (RPC) in Android” I’ve explained the basics on how inter-process communication can be implemented in Android. Now we will take a look at a specialized field in this area: Using Parcelables as parameters of an AIDL method.
As described in the previous post it is possible to either use primitive
java types within a remote method signature or any class which
implements the android.os.Parcelable interface. Using this interface it
is possible to define arbitrarily complex data types which can be used
as parameters or return values of methods during a remote method call.
I’ve created a modified version of the first example app to give you a
basic example which relies on a Parcelable object as a method return
value.
The example consists of a Service which generates a Parcelable message
object containing the current system time and text appearance values
such as the color, the size and the style. In the second part of the
example you can find an Activity which is using the AIDL IPC to retrieve
such a message object to display the current time. The corresponding
projects are called AIDLRemoteClientUsingParcelableObject for the client
project (containing the Activity) and
AIDLRemoteMessageServiceUsingParcelableObject for the server (containing
the Service).
Because this example is just a modified version of the previous one I
will only explain the Parcelable related parts in this post. If you
encounter trouble understanding the context, please refer to the first posting on AIDL.
As always you can browse or download the source code of the example App at our SVN repository at Google Code (http://code.google.com/p/android-aidl-ipc-rpc-example/) or use svn to check the project out and your allowed to reuse portions of this code as you wish.

Fundamentals of Parcels and Parcelables

In Android, Parcels are used to transmit messages. Unlike to the java
serialization, the Parcels are implanted as high-performance containers
for the Android inter process communication. By implementing the
Parcelable interface you declare that it’s possible to transform
(marshall) your class into a Parcel and back (demarshall). Because the
Parcels are designed for performance you should always use Parcelables
instead of using the java serialization (which would also be possible)
when doing IPC in android. Even when you are communicating with Intents
you can still use Parcels to pass data within the intent instead of
serialized data which is most likely not as efficient as Parcels.

The Parcelable Interface

The android.os.Parcelable interface defines two methods which have to be implemented:

int describeContents()

This method can be used to give additional hints on how to process the received parcel. For example, there could be multiple implementations of an Interface which extends the Parcelable Interface. When such a parcel is received, this method can then be to determine which object implementation needs to be instantiated.

void writeToParcel(Parcel dest, int flags)

his is the core method which is called when this object is to be marshalled to a parcel object. In this method all required data fields should be added to the “dest” Parcel so that it’s possible to restore the state of the object within the receiver during the demarshalling. The “flags” parameter indicates if the marshalling was triggered because the object becomes a return value of a remote method (if that’s the case the parameter is set to Parcelable.PARCELABLE_WRITE_RETURN_VALUE). If your model object contains references which could hinder the garbage collector from freeing the resources, you may want to check if the flag is set and remove the references at this moment to free resources which are limited on mobile devices.

Furthermore it is necessary to provide a static CREATOR field in any implementation of the Parcelable interface. The type of this CREATOR must be of Parcelable.Creator<T>. This CREATOR will act as a factory to create objects during the demarshalling of the parcel. For this purpose, the Parcelable.Creator interface defines two methods where the type parameter T represents the Parcelable object:

T createFromParcel(Parcel source)

This method is called during the demarshalling of the object. The parameter source represents the parcel which contains the data of the corresponding object. During this method you can extract the data fields in the same sequence as you put them into the Parcel during the writeToParcel method. These fields can then be used to create an instance of the object.

T[] newArray(int size)

This method returns just an empty array of the object with a given size.

Defining the Parcelable Message Class

Now that we know what we have to implement when creating a class which implements the Parcelable interface, we can define our own message class which will be used in the example. Within the example source code, the MyParcelableMessage class is defined in the com.appsolut.example.aidlMessageServiceUsingParcelable package.

public class MyParcelableMessage implements Parcelable {
    private final String message;
    private final int textSize;
    private final int textColor;
    private final Typeface textTypeface;

These fields represent the state of the message. We have to make sure that the information stored there is not lost during the marshalling or demarshalling process. For the marshaling process, we need to implement the methods defined in the Parcelable interface:

The describeContents Method

public int describeContents() {
    return 0;
}

Because our content has nothing special about it we can just return a zero.

The writeToParcel Method

The writeToParcel method is implemented quite easy as well. The Parcel interface contains methods to write primitve java types such as string, int, etc. We can use these methods to store the object state within the parcel.

public void writeToParcel(Parcel outParcel, int flags) {
    outParcel.writeString(message);
    outParcel.writeInt(textSize);
    outParcel.writeInt(textColor);
    outParcel.writeInt(textTypeface.getStyle());
}

For the demarshalling, we need to remember the sequence in which we have stored the fields in the parcel.

The Parcelable.Creator CREATOR field

The CREATOR field is required for the demarshalling. As previously described, the Parcelable.Creator interface requires us to implement two methods:

public static final Parcelable.Creator<MyParcelableMessage> CREATOR = new Parcelable.Creator<MyParcelableMessage>() {

    @Override
    public MyParcelableMessage createFromParcel(Parcel in) {
        String message = in.readString();
        int fontSize = in.readInt();
        int textColor = in.readInt();
        Typeface typeface = Typeface.defaultFromStyle(in.readInt());
        return new MyParcelableMessage(message, fontSize, textColor, typeface);
    }

    @Override
    public MyParcelableMessage[] newArray(int size) {
        return new MyParcelableMessage[size];
    }
};

During the createFromParcel method we use the read methods which are provided in the Parcel to extract our state information. In the end we create a new MyParcelableMessage object with the corresponding state.

The newArray method just returns an empty array.

Defining the AIDL Files

The AIDL complier won’t be able to locate our self-defined MyParcelableMessage even if it implements the Parcelable interface. To propagate our implementation to the AIDL compiler, we need to define an aidl file which declares the class as Parcelable:

/* The package where the aidl file is located */
package com.appsolut.example.aidlMessageServiceUsingParcelable;

/* Declare our message as a class which implements the Parcelable interface */
parcelable MyParcelableMessage;

Like all aidl files, this file has to be in the same folder as the class file.

Within the aidl file of the remote interface we have to import our Parcelable message so that the AIDL compiler knows about it. This is done by an java like import statement where the full identifier of the class has to be used (package + class).

/* The package where the aidl file is located */
package com.appsolut.example.aidlMessageServiceUsingParcelable;

/* Import our Parcelable message */
import com.appsolut.example.aidlMessageServiceUsingParcelable.MyParcelableMessage;

/* The name of the remote service */
interface IRemoteParcelableMessageService {

    /* A simple Method which will return a message
     * The message object implements the Parcelable interface
     */
    MyParcelableMessage getMessage();

}

Using the Parcelable Class in the Client

In addition to the AIDL remote interface description, you have to provide the defined Parcelable classes to the client because the class files are required to instantiate the objects when performing the remote procedure call. In our example we just copied the .java file together with the corresponding .aidl files to the client project.

Summary and Further Reading

It is quite easy to define own model classes which are Parcelable. So you should always prefer parcels over the use of the default java serialization because the performance can be increased, which is important on mobile devices which might not always use the latest processor or be limited by other resources e.g. the memory. In addition to the performance enhancements, the possibility of using Parcelable model classes further enhances the capabilities of the Android IPC mechanism and increases the ease of use of the remote interface because multiple parameters can be combined into an object.

If you want to get more information on this topic I suggest you refer to the following links:

http://www.app-solut.com/blog/2011/05/using-self-defined-parcelable-objects-during-an-android-aidl-rpc-ipc-call/

by Kevin Kratzer

Using self-defined Parcelable objects during an Android AIDL RPC / IPC call,布布扣,bubuko.com

时间: 2024-12-21 09:25:46

Using self-defined Parcelable objects during an Android AIDL RPC / IPC call的相关文章

android AIDL RPC 机制

AIDL 这是接口文件的叙述性说明,为了实现android 上述平台RPC ,aapt 在编译时自己主动按照该规则IPC 的接口和对象,作为一个用户只需要 实现在服务侧的界面 2 在clientbindService onServiceConnected 接口对象,这里的接口都是AIDL 中描写叙述的接口,其它的细节则在由AIDL 化成同名源文件 这里面有一个接口,里面在的方法就是AIDL 文件里所定义的方法另一个Stub 这个就是要在Service 端实现的基类,另一个Proxy 它们之间的关

Android AIDL开发

Introduction   在Android中, 每个应用程序都运行在自己的进程中,拥有独立的内存空间.但是有些时候我们的应用程序需要跟其它的应用程序进行通信,这个时候该怎么办呢?显然, Java中不允许跨进程内存共享.无法直接交换数据.Android中可以采用AIDL的方式实现进程间通信(interprocess communication(IPC)). Android Developer原文介绍如下:AIDL (Android Interface Definition Language)

Android AIDL 进行进程间通讯(IPC)

编写AIDL文件时,需要注意: 1.接口名和aidl文件名相同. 2.接口和方法前不用加访问权限修饰符 (public.private.protected等,也不能用final.static). 3.AIDL默认支持的类型包括java基本类型 (int.long.boolean等) 和 (String.List.Map.CharSequence),使用这些类型时不需要import声明.对于List和Map中的元素类型必须是AIDL支持的类型,如果使用自定义类型作为参数或者返回值,自定义类型必须实

Android AIDL使用详解

1.什么是aidl:aidl是 Android Interface definition language的缩写,一看就明白,它是一种android内部进程通信接口的描述语言,通过它我们可以定义进程间的通信接口 icp:interprocess communication :内部进程通信 2.既然aidl可以定义并实现进程通信,那么我们怎么使用它呢?文档/android-sdk/docs/guide/developing/tools/aidl.html中对步骤作了详细描述: --1.Create

Android中进程间通信(IPC)方式总结

IPC为进程间通信或跨进程通信,是指两个进程进行进程间通信的过程.在PC和移动设备上一个进程指的是一个程序或者一个应用,所以我们可以将进程间通信简单理解为不同应用之间的通信,当然这种说法并不严谨. 在Android中,为每一个应用程序都分配了一个独立的虚拟机,或者说每个进程都分配一个独立的虚拟机,不同虚拟机在内存分配上有不同的地址空间,这就导致在不同的虚拟机互相访问数据需要借助其他手段.下面分别介绍一下在Android中进行实现IPC的方式. 1.使用Bundle 我们知道在Android中三大

Android开发之IPC进程间通信-AIDL介绍及实例解析

一.IPC进程间通信 IPC是进程间通信方法的统称,Linux IPC包括以下方法,Android的进程间通信主要采用是哪些方法呢? 1. 管道(Pipe)及有名管道(named pipe):管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信:   2. 信号(Signal):信号是比较复杂的通信方式,用于通知接受进程有某种事件发生,除了用于进程间通信外,进程还可以发送信号给进程本身:linux除了支持Unix早期

android aidl摘要

/*在Android中, 每个应用程序都有自己的进程,当需要在不同的进程之间传递对象时,该如何实现呢? 显然, Java中是不支持跨进程内存共享的.因此要传递对象, 需要把对象解析成操作系统能够理解的数据格式, 以达到跨界对象访问的目的.在JavaEE中,采用RMI通过序列化传递对象.在Android中, 则采用AIDL(Android Interface Definition Language:接口描述语言)方式实现. AIDL是一种接口定义语言,用于约束两个进程间的通讯规则,供编译器生成代码

Android AIDL 实现过程

Android系统中的进程之间不能共享内存,因此,需要提供一些机制在不同进程之间进行数据通信.为了使其他的应用程序也可以访问本应用程序提供的服务,Android系统采用了远程过程调用(Remote Procedure Call,RPC)方式来实现.与很多其他的基于RPC的解决方案一样,Android使用一种接口定义语言(Interface Definition Language,IDL)来公开服务的接口.我们知道4个Android应用程序组件中的3个(Activity.BroadcastRece

Android AIDL 小结

1.AIDL (Android Interface Definition Language ) 2.AIDL 适用于 进程间通信,并且与Service端多个线程并发的情况,如果只是单个线程 可以使用 Messenger ,如果不需要IPC 可以使用Binder 3.AIDL语法:基础数据类型都可以适用,List Map等有限适用.static field 不适用. 4.AIDL基本用法 第一步:实现.aidl文件 接口描述文件 1.导入的包名 2.如果有使用Object对象,需要该对象 impl