android ipc通信机制之二序列化接口和Binder
IPC的一些基本概念,Serializable接口,Parcelable接口,以及Binder。此核心为最后的IBookManager.java类!!!
Serializable接口,Parcelable接口都是可以完成对象的序列化过程。
序列化 (Serialization)将对象的状态信息转换为可以存储或传输的形式的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。
两者均可以实现序列化并且都可以用于Intent数据传递,那么如何的选取:
Serializable:是Java的序列化接口,使用简单但是开销很大,序列化反序列化过程需要大量I/O操作。
Parcelable:是Android的序列化接口,更适用于android平台,使用麻烦但是效率高,因此首选Parcelable。
Parcelable主要用于内存序列化上。若为对象序列化刀存储设备或者将对象序列化后进行网络传输最好使用Serializable,较为简单方便。
Paecelable接口:
import android.os.Parcel;
import android.os.Parcelable; public class Book implements Parcelable {
int bookid;
String bookname;
public Book(int bookid,String bookname){
this.bookid=bookid;
this.bookname=bookname;
}
//内容描述功能,几乎所有情况都返回“0”,仅当当前对象中存在文件描述符。
//文件描述符在形式上是一个非负整数。实际上,它是一个索引值,
// 指向内核为每一个进程所维护的该进程打开文件的记录表。
@Override
public int describeContents() {
return 0;
}
//序列化功能 writeToParcel,通过Parcel一系列write方法完成。
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(bookid);
dest.writeString(bookname);
}
//反序列化共嗯那个CREATOR,通过Pancel一系列read方法完成。
public static final Parcelable.Creator<Book> CREATOR = new Parcelable.Creator<Book>(){ @Override
public Book createFromParcel(Parcel source) {
return new Book(source);
} @Override
public Book[] newArray(int size) {
return new Book[size];
}
};
private Book(Parcel source){
bookid = source.readInt();
bookname = source.readString();
}
}
在Paecelable序列化的过程中需要实现序列化、反序列化、内容描述。
- 序列化功能 writeToParcel,通过Parcel一系列write方法完成。
反序列化通过CREATOR,通过Pancel一系列read方法完成。 public static final Parcelable.Creator<Book> CREATOR = new Parcelable.Creator<Book>()
内容描述功能,几乎所有情况都返回“0”,仅当当前对象中存在文件描述符。
文件描述符:在形式上是一个非负整数。实际上,它是一个索引值,指向内核为每一个进程所维护的该进程打开文件的记录表。
Binder:
从android应用层来说,Binder是客户端和服务端进行通讯的媒介,当使用bindSerivice时服务端会返回一个Binder对象,通过这个对象可以获取服务端的服务和数据。
Android开发中,Binder主要用在Service中,包括AIDL和Messenger,普通的Service中的Binder不涉及进程通信,而Messenger的核心是AIDL,现在新建一个AIDL实例。
AIDL:Android Interface Definition Language,即Android接口定义语言。
创建Book.java,Book.aidl,IBookManager.adil
Book.java:如上述代码。
Book.aidl:在android stuido 可以直接new aidl文件,其作用是Book类在AIDL的声明,(在IBokkManager.aidl文件用到了Book类,就需要声明Book.aidl)。其代码如下:

// Book.aidl
package hang.myapplication; // Declare any non-default types here with import statements parcelable Book;
IBookManager.adil:是定义的一个接口,包含getBooklist和addBook方法。
注意:尽管Book类和IBookManager在同一包里,但是依然要导入Book类,这是AIDL的特殊之处。与此同时,系统会自动生成IBookManager.java类
之所以使用AIDL,是为了方便系统帮我们生成代码,也可以不借助AIDL自己书写代码,下面有介绍每个方法。。
// IBook.aidl
package hang.myapplication; // Declare any non-default types here with import statements
import hang.myapplication.Book;
interface IBookManager {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
List<Book> getBookList();
void addBook(in Book book);
}

IBook即为IBookManager,在笔者实例中,此处类名与上述名字有差异。
现在,我们就根据这个java类(系统生成的Binder类)分析Binder的工作原理。
IBookeManager.java:
此处为系统生成代码,较为混乱,可以看文字叙述。核心实现为,内部类stub和其内部代理类proxy。
/*
* This file is auto-generated. DO NOT MODIFY.
* Original file: C:\\Users\\hang\\Documents\\AndroidWorkSpace\\MyApplication\\MyApplication\\IPC\\src\\main\\aidl\\hang\\myapplication\\IBook.aidl
*/
package hang.myapplication;
public interface IBook extends android.os.IInterface
{
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements hang.myapplication.IBook
{
private static final java.lang.String DESCRIPTOR = "hang.myapplication.IBook";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an hang.myapplication.IBook interface,
* generating a proxy if needed.
*/
public static hang.myapplication.IBook asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof hang.myapplication.IBook))) {
return ((hang.myapplication.IBook)iin);
}
return new hang.myapplication.IBook.Stub.Proxy(obj);
}
@Override public android.os.IBinder asBinder()
{
return this;
}
@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
{
switch (code)
{
case INTERFACE_TRANSACTION:
{
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_getBookList:
{
data.enforceInterface(DESCRIPTOR);
java.util.List<hang.myapplication.Book> _result = this.getBookList();
reply.writeNoException();
reply.writeTypedList(_result);
return true;
}
case TRANSACTION_addBook:
{
data.enforceInterface(DESCRIPTOR);
hang.myapplication.Book _arg0;
if ((0!=data.readInt())) {
_arg0 = hang.myapplication.Book.CREATOR.createFromParcel(data);
}
else {
_arg0 = null;
}
this.addBook(_arg0);
reply.writeNoException();
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
private static class Proxy implements hang.myapplication.IBook
{
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote)
{
mRemote = remote;
}
@Override public android.os.IBinder asBinder()
{
return mRemote;
}
public java.lang.String getInterfaceDescriptor()
{
return DESCRIPTOR;
}
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
@Override public java.util.List<hang.myapplication.Book> getBookList() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
java.util.List<hang.myapplication.Book> _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_getBookList, _data, _reply, 0);
_reply.readException();
_result = _reply.createTypedArrayList(hang.myapplication.Book.CREATOR);
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
@Override public void addBook(hang.myapplication.Book book) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
if ((book!=null)) {
_data.writeInt(1);
book.writeToParcel(_data, 0);
}
else {
_data.writeInt(0);
}
mRemote.transact(Stub.TRANSACTION_addBook, _data, _reply, 0);
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}
}
static final int TRANSACTION_getBookList = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_addBook = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
}
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
public java.util.List<hang.myapplication.Book> getBookList() throws android.os.RemoteException;
public void addBook(hang.myapplication.Book book) throws android.os.RemoteException;
}
Binder类
关键方法:
getBooklist、addBook:这是在IBookManager.aidl中声明的方法,同时在 IBookeManager.java 中为其声明了两个整型的id,分别标识这两个方法。
内部类Stub:其就是Binder类,当客户端和服务端在同一进程时,方法调用不会走进跨进程的transact过程。而位于不同进程时,则会执行该方法。这个逻辑
由Stub的内部代理Proxy来完成。
详细介绍:
- asInterface:用于将客户端的Binder对象转换成客户端所需要的AIDL接口类型对象,如果客户端和服务端位于同一进程,返回服务端的Stub对象本身。否则,
返回Stub.proxy对象。
DESCRIPTOR:Binder的唯一标识,一般是当前Binder的类名。
public static hang.myapplication.IBook asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof hang.myapplication.IBook))) {
return ((hang.myapplication.IBook)iin);
}
return new hang.myapplication.IBook.Stub.Proxy(obj);
}
- asBinder:返回当前Binder对象。
- boolean onTransact: 全方法为,onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags)
int code:可以确定客户端的目标方法是什么?可以看到switch case结构。
android.os.Parcel data:从这里取出目标方法的所需参数(如果目标方法有参数的话)。然后执行目标方法。
android.os.Parcel reply:目标方法执行完成后,向reply写入返回值(如果目标方法有返回值)。
以上亦为执行步骤~
目标方法:此案例getBooklist、addBook就是其中的目标方法。
若此方法返回false,那么客户端的请求会失败,可利用这一特性做权限验证。
- Proxy#getBooklist和Proxy#addBook:~~~~~~~
若是自定义,记得写上这些方法。
下一章,Android的各种跨进程通讯方式。
android ipc通信机制之二序列化接口和Binder的更多相关文章
- android ipc通信机制之之三,进程通讯方式。
IPC通讯方式的优缺点: IPC通讯方式的对比 名称 优点 缺点 适用场景 Bundle 简单易用 只能传输Bundle支持的数据类型 四大组件的进程通信 文件共享 简单易用 不适合高并发场景,并无法 ...
- android IPC通信(上)-sharedUserId&&Messenger
看了一本书,上面有一章解说了IPC(Inter-Process Communication,进程间通信)通信.决定结合曾经的一篇博客android 两个应用之间的通信与调用和自己的理解来好好整理总结一 ...
- python 之 并发编程(守护进程、互斥锁、IPC通信机制)
9.5 守护进程 主进程创建守护进程 其一:守护进程会在主进程代码执行结束后就立即终止 其二:守护进程内无法再开启子进程,否则抛出异常:AssertionError: daemonic process ...
- Android 进程通信机制之 AIDL
什么是 AIDL AIDL 全称 Android Interface Definition Language,即 安卓接口描述语言.听起来很深奥,其实它的本质就是生成进程间通信接口的辅助工具.它的存在 ...
- Android多线程通信机制
掌握Android的多线程通信机制,我们首先应该掌握Android中进程与线程是什么. 1. 进程 在Android中,一个应用程序就是一个独立的进程(应用运行在一个独立的环境中,可以避免其他应用程序 ...
- android 休眠唤醒机制分析(二) — early_suspend
本文转自:http://blog.csdn.net/g_salamander/article/details/7982170 early_suspend是Android休眠流程的第一阶段即浅度休眠,不 ...
- 架构师成长之路-基于android fragment通信的面向对象的万能接口
前言 开发一个app时,常用Activity和Fragment,由于操作方便Fragment越来越受欢迎,这样就避免不了Activity和Fragment.Fragment和Fragment之间的通信 ...
- Android包管理机制(二)PackageInstaller安装APK
前言 在本系列上一篇文章Android包管理机制(一)PackageInstaller的初始化中我们学习了PackageInstaller是如何初始化的,这一篇文章我们接着学习PackageInsta ...
- Android IPC通信和AIDL技术应用
首先我们了解一下 IPC和AIDL IPC:进程间通信 AIDL:Android Interface Definition Language,即Android接口定义语言. 为什么使用: Androi ...
随机推荐
- 简单分析什么是SQL注入漏洞
现在很多人在入侵的过程中基本都是通过SQL注入来完成的,但是有多少人知道为什么会有这样的注入漏洞呢?有的会随口说着对于字符的过滤不严造成的.但是事实是这样吗?我们学这些,不仅要知其然,更要知其所以然! ...
- uva 11624 Fire!(搜索)
开始刷题啦= = 痛并快乐着,学到新东西的感觉其实比看那些无脑的小说.电视剧有意思多了 bfs裸体,关键是先把所有的着火点放入队列,分开一个一个做bfs会超时的 发现vis[][]是多余的,完全可以用 ...
- Android精美的日历控件
网上看到的精美日历控件,谨以此文记录一下,用到的时候再来翻翻 源码地址 : http://download.csdn.net/detail/abc13939746593/7265459
- why dicePlayer cannot player with defy mb526
硬件加速视频播放器 DicePlayer v2.0.38 ... ..... ...... ........ \ 局限性:- 视频兼容性依赖于您设备的视频硬解码能力
- [转]python类方法
Python定义类-方法 公有方法.私有方法.类方法.静态方法
- ZOJ 3879 Capture the Flag
以此题纪念我写的第一篇acm博客,第一道模拟:) http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3879 题意非常复杂,感觉 ...
- hadoop2.20.0集群安装教程
一.安装的需要软件及集群描述 1.软件: Vmware9.0:虚拟机 Hadoop2.2.0:Apache官网原版稳定版本 JDK1.7.0_07:Oracle官网版本 Ubuntu12.04LTS: ...
- java web 学习一
一.基本概念 1.1.WEB开发的相关知识 WEB,在英语中web即表示网页的意思,它用于表示Internet主机上供外界访问的资源. Internet上供外界访问的Web资源分为: 静态web资源( ...
- C/C++面试小知识点
1.static有什么用途. 解答: 在函数体中,一个被声明为静态的变量在这一函数被调用过程中维持其值不变. 在模块内(但在函数体外),一个被声明为静态的变量可以被模块内所有函数访问,但不能被模块外其 ...
- LightOJ 1038-Race to 1 Again(概率dp)
题意: 给你一个数n每一步这个数可以变为他的因子,直到这个数变为1,求n变到1的期望步数. 分析: dp[i],表示i变为1的期望步数,dp[1]=0,dp[n]是答案. dp[i]=sum(dp[j ...