Android IPC、Binder和AIDL

1、前言 IPC

PC(Inter-Process Communication)进程间通信,提供了各种进程间通信的方法。不仅是Android,其他语言也大很多情况下需要进程间通信的。Android本质上属于Linux,它的跨进程通信也基于Linux进程通信的原理。在Linux C编程中有几种方法
(1) 半双工Unix管道
(2) FIFOs(命名管道)
(3) 消息队列
(4) 信号量
(5) 共享内存
(6) 网络Socket

以上方法都可以实现进程间的通讯,但Android并没有使用以上6种现成的通信方法,而是自己开发Binder驱动,至于为什么重新开发Binder,可参考知乎上的回答:
https://www.zhihu.com/question/39440766?sort=created

大致原因:安全,性能,稳定。
本篇大致围绕下面几个问题,大致做出回答

  1. 什么是IPC,大致适应场景
  2. Binder机制
  3. Binder与AIDL
  4. 如何使用AIDL

1、为什么会有IPC?

因为在很多情况下,我们需要共享进程或者进程间通信,场景
1、下载的音乐文件在文件管理器中,当前我正在播放因为,我在文件管理器删除音乐(文件不存在了),当前音乐播放器是不是该停止呢?
2、第三方APP集成支付宝付款时,第三方应用怎么样调起支付宝用于支付呢
其实使用的场景很多,要实现上面的功能就得使用IPC。
Android IPC、Binder和AIDL_第1张图片

内存共享

在用户空间中没有办法共享,因此进程间不能通信,但在内核空间中可以共享,不同的APP要进行通信,可以通过使用内核空间来做到,这样就产生IPC机制,IPC是用于解决这些问题的。为了做到IPC,Android 中提供了Binder机制,来解决进程通信问题

2、Binder机制

Android IPC、Binder和AIDL_第2张图片
服务端:Binder服务端其实就是一个Binder对象,对象建立后,启动一个线程,这个线程接收Binder驱动发送的消息,并执行onTransact()方法,执行服务代码。
Binder驱动:当服务端对象创建时,同时会在Binder驱动中创建一个mRemote对象,该对象类型也是Binder类,客户端要过程访问时,都是通过mRemote对象。
客户端:客户端想要访问远程服务时,必须获取远程服务在B inder中对应的mRemote 对象,获取方法就是通过AIDL

3、Binder与AIDL

AIDL(Android Interface Define Language),是android的一种接口定义语言。借助它,你可以定义接口,使得客户端和服务端之间实现进程间通信。
Binder是Android的一个类,它实现了IBinder接口。从IPC角度来说,Binder是android中的一种跨进程通信方式。通过这个Binder对象,客户端就可以获取服务端提供的服务或数据,这里的服务包括普通服务和基于AIDL的服务。

也就是说Binder是用来实现远程服务访问的,AIDL则主要负责远程访问的主要内容,这些内容则用AIDL中的接口来描述。

4、AIDL使用示例

示例做一个进程间通信的Demo,在AIDLServer中新建一个方法,返回一个字符串,在另一个Client的APP中调用。
Android IPC、Binder和AIDL_第3张图片

1、服务端代码

1.创建一个AIDL文件:

// IMyAidlInterface.aidl
package com.example.aidlservice;

// Declare any non-default types here with import statements

interface IMyAidlInterface {
    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
            double aDouble, String aString);


    String getString();
}

2、新建服务,这个服务就是远程访问的服务,用于客户端调用

package com.example.aidlservice;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.annotation.Nullable;

/**
 * Created by yuxiaogang on 2017/8/5.
 */

public class RemoteService extends Service {
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return iMyAidlInterface;
    }

    private IMyAidlInterface.Stub iMyAidlInterface = new IMyAidlInterface.Stub() {
        @Override
        public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {

        }

        @Override
        public String getString() throws RemoteException {
            return "im from server";
        }


    };
}

3、启动服务:

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private Button btn_bind;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btn_bind = (Button) findViewById(R.id.btn_bind);
        btn_bind.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn_bind:
                Intent intent = new Intent(this, RemoteService.class);
                bindService(intent, new ServiceConnection() {
                    @Override
                    public void onServiceConnected(ComponentName name, IBinder service) {
                        Toast.makeText(MainActivity.this, "success", Toast.LENGTH_SHORT).show();
                    }

                    @Override
                    public void onServiceDisconnected(ComponentName name) {
                        Toast.makeText(MainActivity.this, "failed", Toast.LENGTH_SHORT).show();
                    }
                }, BIND_AUTO_CREATE);
                break;
        }
    }
}

2、客户端

客户端就是实际上需要调用远程服务,首先引进AIDL文件,注意AIDL文件的位置和包名。可以直接从Service中复制过来。编译后,客户端就可以调用到服务端的方法了

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private Button btn_msg;
    private TextView text;
    private IMyAidlInterface iMyAidlInterface;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btn_msg = (Button) findViewById(R.id.btn_msg);
        text = (TextView) findViewById(R.id.text);
        btn_msg.setOnClickListener(this);

    }

    @Override
    protected void onResume() {
        super.onResume();
        Intent intent = new Intent();
        intent.setAction("com.example.aidlservice.RemoteService");
       // intent.setPackage("com.example.aidlservice");
        bindService(intent, new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                iMyAidlInterface=IMyAidlInterface.Stub.asInterface(service);
                Log.i("MainActivity", "onServiceConnected");
            }

            @Override
            public void onServiceDisconnected(ComponentName name) {
                Log.i("MainActivity", "onServiceDisconnected");
            }
        }, BIND_AUTO_CREATE);

    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn_msg:
                try {
                    text.setText(iMyAidlInterface.getString());
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
                break;
        }
    }
}

你可能感兴趣的:(android基础)