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:
- Android Interface Definition Language (AIDL)
- Android Interface Definition Language (AIDL): Passing Objects
- Android API Reference: Parcel
- Android API Reference: Parcelable
- Android API Reference: Parcelable.Creator
- Android API Reference: IBinder
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的更多相关文章
- android AIDL RPC 机制
AIDL 这是接口文件的叙述性说明,为了实现android 上述平台RPC ,aapt 在编译时自己主动按照该规则IPC 的接口和对象,作为一个用户只需要 实现在服务侧的界面 2 在clientbin ...
- Android中的IPC机制
Android IPC简介 IPC是Inter-Process Communication的缩写,含义就是进程间通信或者跨进程通信,是指两个进程之间进行数据交换的过程.那么什么是进程,什么是线程,进程 ...
- Android AIDL 进行进程间通讯(IPC)
编写AIDL文件时,需要注意: 1.接口名和aidl文件名相同. 2.接口和方法前不用加访问权限修饰符 (public.private.protected等,也不能用final.static). 3. ...
- Android开发之IPC进程间通信-AIDL介绍及实例解析
一.IPC进程间通信 IPC是进程间通信方法的统称,Linux IPC包括以下方法,Android的进程间通信主要采用是哪些方法呢? 1. 管道(Pipe)及有名管道(named pipe):管道可用 ...
- Android AIDL 实例
为使应用程序之间能够彼此通信,Android提供了IPC (Inter Process Communication,进程间通信)的一种独特实现: AIDL (Android Interface Def ...
- android AIDL示例代码(mark下)
1.demo结构图 2.ipcclient Book类. package com.mu.guoxw.ipcclient; import android.os.Parcel; import androi ...
- (转载)你真的理解Android AIDL中的in,out,inout么?
前言 这其实是一个很小的知识点,大部分人在使用AIDL的过程中也基本没有因为这个出现过错误,正因为它小,所以在大部分的网上关于AIDL的文章中,它都被忽视了——或者并没有,但所占篇幅甚小,且基本上都是 ...
- Android AIDL使用详解_Android IPC 机制详解
一.概述 AIDL 意思即 Android Interface Definition Language,翻译过来就是Android接口定义语言,是用于定义服务器和客户端通信接口的一种描述语言,可以拿来 ...
- Android下的IPC通信方式
一.Bundle Android的Activity.Service.Receiver都支持在Intent传递Bundle数据,Bundle实现了Parcelable接口, 所以能很方便的在不同进程之间 ...
随机推荐
- Java作业 输入圆的半径计算输出圆的周长和面积
package text1; import java.util.Scanner; public class text11 { public static void main(String[] args ...
- Miniui updateRow更改列字段值
当UPC等于upccode时,更改列Scanned+1 //先grid.findRow找到UPC等于upccode的行对象 var row = grid.findRow(function (row) ...
- CSS之text-stroke
啧啧啧( ̄︶ ̄),国庆人太多,所以假期还没结束就提前几天回来了.今天也是挤火车赶回来的,被夹在门里好尴尬啊~~ 回家的这几天在外婆家招待过的好爽啊,又是鱼又是肉,馋的我都不想走了. 然而自己在家只能“ ...
- 收集一下Windows7系统啊
Windows7系统:http://down.662p.com/list/141_1.html 萝卜家园WIN7系统X86位旗舰特别GHOST版2014年12月 这个是萝卜家园WIN7系统X86位 ...
- windows Api AlphaBlend的使用方法
很早的时候公司里开发了个c++客户端软件,需要支持windows2000,要求简单小巧,并且不希望引入其他界面库,图形引擎之类的东西,像gdi+之类的,于是对于美工做出来的一些界面,需要有alpha通 ...
- jQuery自定义Web页面鼠标右键菜单
jQuery自定义Web页面鼠标右键菜单 右键菜单是固定的,很多时候,我们需要自定义web页面自定义菜单,指定相应的功能. 自定义的原理是:jQuery封装了鼠标右键的点击事件(“contextmen ...
- Apple Watch开发之界面之间的正向传值
主要分两种,一种是故事板中通过segue进行的传值,第二种是使用代码. 贴代码 24行代码是代码进行传值 35是故事板中的
- Regsvr32注册ActiveX控件
命令:Regsvr32 XX.dll 注册ActiveX控件 Regsvr32命令参数:/u 卸载ActiveX控件/s 注册成功后不显示操作成功信息框/c 控制台输出/I 调用DllInstall安 ...
- OC3-xml文件解析
<?xml version="1.0"?> <xml_api_reply version="1"> <cities> < ...
- 一个简单的Spring测试的例子
在做测试的时候我们用到Junit Case,当我们的项目中使用了Sring的时候,我们应该怎么使用spring容器去管理我的测试用例呢?现在我们用一个简单的例子来展示这个过程. 1 首先我们新建一个普 ...