android IPC 进程间通信 Binder AIDL

只有当你允许来自不同的客户端访问你的服务并且需要处理多线程问题时你才必须使用AIDL”,其他情况下你都可以选择其他方法,如使用Messager,也能跨进程通讯。可见AIDL是处理多线程、多客户端并发访问的。而Messager是单线程处理。 这就明白了 为什么要有aidl

线程
进程
关系
线程 是CPU 调度最小单位
进程指的是一个执行单元,如程序或者一个应用

首先开启多进程 就相当于多开了一个应用
先来想想带来的不良影响
1 静态成员和单例模式完全失效
2 线程同步机制完全失效
3 sharepreference的可靠性下降
4 Application会多次被创建

下面来一些基础介绍
1 Serializable接口
这是java提供的一个序列化接口
如何进行序列化和反序列化呢


image.png

android的序列化方式
Parcelable
他也是一个接口 只要是实现这个接口 一个类的对象就可以实现序列化并可以通过Intent和Binder传递


image.png
image.png
image.png

Binder 是android中的一个类 他实现了Ibinder接口 从IPC 角度来说 binder 是android中的一种跨进程通信方式

想要了解 binder 在来了解一个知识点


image.png

内核层:Linux 内核和各类硬件设备的驱动,这里需要注意的是,Binder IPC 驱动也是在这一层实现,比较特殊
硬件抽象层:封装「内核层」硬件驱动,提供可供「系统服务层」调用的统一硬件接口
系统服务层:提供核心服务,并且提供可供「应用程序框架层」调用的接口
Binder IPC 层:作为「系统服务层」与「应用程序框架层」的 IPC 桥梁,互相传递接口调用的数据,实现跨进层的通讯
应用程序框架层:这一层可以理解为 Android SDK,提供四大组件,View 绘制体系等平时开发中用到的基础部件

一个IPC通讯我们可以简单理解成客户端-服务器模式,客户端请求服务,服务端接收到客户端请求后处理相应,或可能带回结果返回给客户端。binder机制在android系统的进程间通讯模型总结如下:
(1)客户端通过某种方式得到服务器端的代理对象。从客户端角度看来代理对象和他的本地对象没有什么差别。它可以像其他本地对象一样调用其方法,访问其变量。
(2)客户端通过调用代理对象的方法向服务器端发送请求信息。
(3)代理对象通过binder设备节点(/dev/binder),把用户请求信息发送到Linux内核空间(实际上是内存共享),由Binder驱动获取并发送到服务进程。
(4)服务进程处理用户请求,并通过Linux内核的Binder驱动返回处理结果给客户端的代理对象。
(5)客户端收到服务端的返回结果。
整个过程大致如上所述,可以想象一下bingder机制的引入,给进程间的通讯带来什么好处?没错,就是“线程迁移”,就像是一个线程带着参数,进入另一个进程执行,然后带着结果返回,和调用自己的函数一样的效果。

上面都是一些概念
看的我也是 晕头转向

image.png
image.png
image.png

看到这里大家有没有晕头转向的感觉 这到底是干嘛的?

image.png

完全不懂啊

ipc binder aidl 这是干啥的 我们开发到底用的到吗? 完全不清楚啊

下面我们来 讨论几点
当我们做一款 音频软件的时候!当播放某一个音乐的时候。我们在干别的时候(这款软件的其他功能)会不会影响到播放呢? 答案是不会的。所以这个播放软件的功能要放在一个新的进程中。 这样就不会有相互的影响。但是这个和我们上面说的有什么关系吗? 哇卡卡。 注意到了吗 这个就是两个不同的进程通信。 剩下的我们来慢慢分析。


image.png

我们写的app。有的时候会和系统的某些功能区交互。比如获取手机号。uuid。等。 app是一个新的app ,我们就需要用ipc 进程间通信。 盗图一张

image.png

每一个系统功能都有一个与之对象manager。

下面看binder 又盗图一张


image.png

Binder IPC 属于 C/S 结构,Client 部分是用户代码,用户代码最终会调用 Binder Driver 的 transact 接口,Binder Driver 会调用 Server,这里的 Server 与 service 不同,可以理解为 Service 中 onBind 返回的 Binder 对象,请注意区分下。

Client:用户需要实现的代码,如 AIDL 自动生成的接口类
Binder Driver:在内核层实现的 Driver
Server:这个 Server 就是 Service 中 onBind 返回的 IBinder 对象
最后一句话怎么理解? 就是我们自己写服务的时候那个方法的返回值

http://www.jianshu.com/p/bdef9e3178c9 这是调用地址。 有很多概念 很棒

顺势我在粘过来几个

IReporter.aidl

package com.android.binder;

interface IReporter {

int report(String values, int type);

}
Server

AidlService.java

public class AidlService extends Service {

public static final class Reporter extends IReporter.Stub {

    @Override
    public int report(String values, int type) throws RemoteException {
        return type;
    }
}

private Reporter mReporter;

public AidlService() {
    mReporter = new Reporter();
}

@Override
public IBinder onBind(Intent intent) {
    return mReporter;
}

}
这里与手动实现的方式不同的是,一个继承了 Binder,一个继承了 AIDL 自动生成的 Stub 对象,它是什么呢?我们可以看下它的定义
...

IReporter.java

public interface IReporter extends android.os.IInterface
{

public static abstract class Stub extends android.os.Binder implements com.android.binder.IReporter {
    ...

    @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_report:
            {
                data.enforceInterface(DESCRIPTOR);
                java.lang.String _arg0;
                _arg0 = data.readString();
                int _arg1;
                _arg1 = data.readInt();
                int _result = this.report(_arg0, _arg1);
                reply.writeNoException();
                reply.writeInt(_result);
                return true;
            }
        }
        return super.onTransact(code, data, reply, flags);
    }
}

...

}
其实和我们上文的写法是一样的,自动生成的 IReporter 类自动给我们处理了一些参数的组包和解包而已,在 case 语句中调用了 this.report 即可调用到自己的业务逻辑部分了。

Client

MainActivity.java

private IReporter mReporterAidl;

private class AidlConnection implements ServiceConnection {

@Override
public void onServiceConnected(ComponentName name, IBinder service) {
    mReporterAidl = IReporter.Stub.asInterface(service);
}

@Override
public void onServiceDisconnected(ComponentName name) {
    mReporterAidl = null;
}

}

...

@Override
protected void onCreate(Bundle savedInstanceState) {

...

Intent intent = new Intent(this, AidlService.class);
bindService(intent, new AidlConnection(), BIND_AUTO_CREATE);

}

这里与手动实现方式也有区别,即调用了 Stub 对象的 asInterface,具体做了什么呢?

public static com.android.binder.IReporter asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.android.binder.IReporter))) {
return ((com.android.binder.IReporter)iin);
}
return new com.android.binder.IReporter.Stub.Proxy(obj);
}
先查找本地接口是否存在,判断是否是本地调用,如果是则直接返回 IReporter 的对象,否则返回 Stub.Proxy 对象,这个 Proxy 对象是做什么的呢?

private static class Proxy implements com.android.binder.IReporter
{
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;
}
@Override public int report(java.lang.String values, int type) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
int _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeString(values);
_data.writeInt(type);
mRemote.transact(Stub.TRANSACTION_report, _data, _reply, 0);
_reply.readException();
_result = _reply.readInt();
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
}
...
基本上已经很明了了,就是一个代理对象,对调用接口参数做组包而已,然后调用了 mRemote.transact 接口,和上文手动实现的方式是一致的。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容