android ipc通信机制之二序列化接口和Binder

IPC的一些基本概念,Serializable接口,Parcelable接口,已经Binder。此核心为最后的IBookManager.java类!!!

Serializable接口,Parcelable接口都是可以完成对象的序列化过程。

序列化 (Serialization)将对象的状态信息转换为可以存储或传输的形式的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。

两者均可以实现序列化并且都可以用于Intent数据传递,那么如何的选取:

  Serializable:是Java的序列化接口,使用简单但是开销很大,序列化反序列化过程需要大量I/O操作。

  Parcelable:是Android的序列化接口,更适用于android平台,使用麻烦但是效率高,因此首选Parcelable。

  Parcelable主要用于内存序列化上。若为对象序列化刀存储设备或者将对象序列化后进行网络传输最好使用Serializable,较为简单方便。



Paecelable接口:

 1 import android.os.Parcel;
 2 import android.os.Parcelable;
 3
 4 public class Book implements Parcelable {
 5     int bookid;
 6     String bookname;
 7     public Book(int bookid,String bookname){
 8         this.bookid=bookid;
 9         this.bookname=bookname;
10     }
11     //内容描述功能,几乎所有情况都返回“0”,仅当当前对象中存在文件描述符。
12     //文件描述符在形式上是一个非负整数。实际上,它是一个索引值,
13     // 指向内核为每一个进程所维护的该进程打开文件的记录表。
14     @Override
15     public int describeContents() {
16         return 0;
17     }
18     //序列化功能 writeToParcel,通过Parcel一系列write方法完成。
19     @Override
20     public void writeToParcel(Parcel dest, int flags) {
21         dest.writeInt(bookid);
22         dest.writeString(bookname);
23     }
24     //反序列化共嗯那个CREATOR,通过Pancel一系列read方法完成。
25     public static final  Parcelable.Creator<Book> CREATOR = new Parcelable.Creator<Book>(){
26
27         @Override
28         public Book createFromParcel(Parcel source) {
29             return new Book(source);
30         }
31
32         @Override
33         public Book[] newArray(int size) {
34             return new Book[size];
35         }
36     };
37     private Book(Parcel source){
38         bookid = source.readInt();
39         bookname = source.readString();
40     }
41 }

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的声明。其代码如下:

// 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的各种跨进程通讯方式。

  

时间: 2024-08-01 10:22:07

android ipc通信机制之二序列化接口和Binder的相关文章

Android IPC通信机制之一

IPC:Intent-process Communication,跨进程通信. 在一个应用程序中,可以很方便的开启多进程.开启进程的方式只有一种,只能在AndroidMenifest中为四大组件指定 Android:process属性. 在非常规情况下,也可以通过JNI在native层去fork一个新的进程. <activity android:name=".MainActivity" android:label="@string/app_name" andr

android ipc通信机制之之三,进程通讯方式。

IPC通讯方式的优缺点: IPC通讯方式的对比 名称 优点 缺点 适用场景 Bundle 简单易用 只能传输Bundle支持的数据类型 四大组件的进程通信 文件共享 简单易用 不适合高并发场景,并无法做到进程间即时通讯. 无并发访问情形,交换简单的数据是实时性不高的场景. AIDL 功能强大,支持一对多并发通信,支持实时通信. 使用稍微复杂,需要处理好线程同步. 一对多通信且有RPC需求 Messenger 功能一般,支持一对多串行通信,支持实时通信. 不能很好处理高并发情形,不支持RPC,数据

android IPC通信(下)-AIDL

android IPC通信(上)-sharedUserId&&Messenger android IPC通信(中)-ContentProvider&&Socket 这篇我们将会着重介绍AIDL的使用方式和原理,要介绍AIDL先要简单介绍一下Binder,而且Messenger,ContentProvider和AIDL的最底层都是使用的Binder. Binder 直观来说,Binder是Android中的一个类,它实现了IBinder接口.从IPC角度来说,Binder是A

android IPC通信(上)-sharedUserId&amp;amp;&amp;amp;Messenger

看了一本书,上面有一章解说了IPC(Inter-Process Communication,进程间通信)通信.决定结合曾经的一篇博客android 两个应用之间的通信与调用和自己的理解来好好整理总结一下这块的知识.因为内容较多,这部分会分上中下三篇博客来细致分析解说,第一篇上篇要解说的是sharedUserId和Messenger的使用方式. android IPC通信(中)-ContentProvider&&Socket android IPC通信(下)-AIDL sharedUserI

android 休眠唤醒机制分析(二) — early_suspend

本文转自:http://blog.csdn.net/g_salamander/article/details/7982170 early_suspend是Android休眠流程的第一阶段即浅度休眠,不会受到wake_lock的阻止,一般用于关闭lcd.tp等设备为运行的应用节约电能.Android的PowerManagerService会根据用户的操作情况调整电源状态,如果需要休眠则会调用到HAL层的set_screen_state()接口,在set_screen_state()中会向/sys/

python—day29 守护进程、互斥锁、模拟抢票、IPC通信机制、生产者消费者模型

1.守护进程: 什么是守护进程,假如你是皇帝,每日每夜守护你的就是太监,守护进程就相当于太监,当皇帝驾崩后太监也需要陪葬,所以守护进程当父进程销毁时就一起销毁: 1 from multiprocessing import Process 2 3 import time 4 5 def task(name): 6 7 time.sleep(0.5) 8 print('%s' %name) 9 10 11 if __name__ == '__main__': 12 p = Process(targe

Android 进程通信机制之 AIDL

什么是 AIDL AIDL 全称 Android Interface Definition Language,即 安卓接口描述语言.听起来很深奥,其实它的本质就是生成进程间通信接口的辅助工具.它的存在形式是一种 .aidl 文件,开发者需要做的就是在该文件中定义进程间通信的接口,编译的时候 IDE 就会根据我们的 .aidl 接口文件生成可供项目使用的 .java 文件,这和我们说的"语法糖"有些类似. AIDL 的语法就是 java 的语法,就是导包上有点细微差别.java 中如果两

架构师成长之路-基于android fragment通信的面向对象的万能接口

前言 开发一个app时,常用Activity和Fragment,由于操作方便Fragment越来越受欢迎,这样就避免不了Activity和Fragment.Fragment和Fragment之间的通信,我们知道Fragment和Fragment之间不能直接进行通信的,而是通过Activity进行通信.那么Activity和Fragment有几种通信方式呢,它们的优缺点又是什么? 一 常用的Activity和Fragment几种通信方式 1 通过Handle 在Activity创建一个Handle

Android包管理机制(二)PackageInstaller安装APK

前言 在本系列上一篇文章Android包管理机制(一)PackageInstaller的初始化中我们学习了PackageInstaller是如何初始化的,这一篇文章我们接着学习PackageInstaller是如何安装APK的.本系列文章的源码基于Android8.0. 1.PackageInstaller中的处理 紧接着上一篇的内容,在PackageInstallerActivity调用startInstallConfirm方法初始化安装确认界面后,这个安装确认界面就会呈现给用户,用户如果想要