Binder:从应用层面上来看,binder是进程间通信的媒介,从framework层看,它是各种Manager(比如WindowManager,ActivityManager)等和相应的ManagerService(WindowManagerService,ActivityManagerService)进行通信的桥梁。从硬件层面来看,它也像是个binder 驱动。它实现了IBinder接口。它是android特有的一种跨进程的通信方式,它的的作用是Android 的进程间进行通信。
下面看看如何使用Binder进行进程间的通信。
1.首先在app目录的src/main目录下,新建一个aidl的文件夹,然后在adil文件夹下,右键,package,包名就填写manifest文件中 的包名。
2.在新建的包的目录下,创建IPalyInterface.aidl文件和IDownLoadInterface.aidl文件以及IBindPool.aidl文件,下面分别是三个文件中的内容:
// IPlayInterface.aidl
package test.cn.example.com.androidskill;
// Declare any non-default types here with import statements
interface IPlayInterface {
/**
* 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);
void palyMusic(String musicName);
}
IDownLoadInterface.adil文件
// IDownLoadInterface.aidl
package test.cn.example.com.androidskill;
// Declare any non-default types here with import statements
interface IDownLoadInterface {
/**
* 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);
void downLoad(String url);
}
IBindPoolInterface.aidl文件
// IBindPoolInterface.aidl
package test.cn.example.com.androidskill;
// Declare any non-default types here with import statements
interface IBindPoolInterface {
IBinder queryBinder(int requestCode);
}
创建完这三个aidl文件后,点击Build选项下的Make Project 按钮,项目完成构建后,在
app/build/generate/sorce/adil/ceshi/debug/包名/ 这个目录下,就会看到生成的相应的IPlayInterface,IDownLoadInterface , IBindPoolInterface三个java文件。完成这个步骤后,其实就已经生成了Binder了。如果不是很明白,可以参考这篇博客:
《Android Studio中如何建立AIDL文件&生成及找到相应的.java文件》
3.新建一个类名为 BindPoolService的java文件,记得在manifest文件中注册,并设置process属性,使其运行在一个单独的进程中。下面是BindPoolService.java的代码:
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.os.Process;
import androidx.annotation.Nullable;
import test.cn.example.com.androidskill.art.chapter_two.BindPool;
import test.cn.example.com.util.LogUtil;
public class BindPoolService extends Service {
private Binder mBinder;
@Override
public void onCreate() {
super.onCreate();
LogUtil.e("onCreate "+"Process.myPid()= "+ Process.myPid());
mBinder = new BindPool.IBindPoolImpl();
}
@Nullable
@android.support.annotation.Nullable
@Override
public IBinder onBind(Intent intent) {
LogUtil.e("mBinder = "+mBinder);
return mBinder;
}
@Override
public void onDestroy() {
super.onDestroy();
LogUtil.e("onDestroy ");
}
}
在onBind方法中返回的mBinder是BindPool类中的静态类,下面看看BindPool类的代码:
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;
import java.util.concurrent.CountDownLatch;
import test.cn.example.com.androidskill.IBindPoolInterface;
import test.cn.example.com.androidskill.service.BindPoolService;
import test.cn.example.com.util.LogUtil;
public class BindPool {
private static final int REQUEST_CODE_PLAYMUSIC = 1;
private static final int REQUEST_CODE_DOWNLOAD = 2;
private final Context mContext;
private CountDownLatch countDownLatch;
private static BindPool instance;
private static IBindPoolInterface iBindPoolInterface;
private BindPool(Context context){
mContext = context.getApplicationContext();
connectService(mContext);
}
private synchronized void connectService(Context context) {
countDownLatch = new CountDownLatch(1);
Intent intent = new Intent(context, BindPoolService.class);
context.bindService(intent,mServiceConnection,Context.BIND_AUTO_CREATE);
try {
//这里要等待,连接上Servcie后,才能继续执行queryBinder方法,否则,queryBinder方法中的
// iBindPoolInterface 就是 null
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static BindPool getInstance(Context context){
if(null == instance){
synchronized (BindPool.class){
if(null == instance){
instance = new BindPool(context);
}
}
}
return instance;
}
private ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
LogUtil.e("servcie connected ");
iBindPoolInterface = IBindPoolInterface.Stub.asInterface(service);
try {
iBindPoolInterface.asBinder().linkToDeath(mBinderPoolDeathRecipient,0);
} catch (RemoteException e) {
e.printStackTrace();
}
//和服务端连接成功后,就解除阻塞的线程,这样queryBinder方法才能执行
countDownLatch.countDown();
}
@Override
public void onServiceDisconnected(ComponentName name) {
LogUtil.e("service disconnect ");
}
};
public void disconnectServcie(){
if(null != mServiceConnection && null != mContext){
mContext.unbindService(mServiceConnection);
}
}
private IBinder.DeathRecipient mBinderPoolDeathRecipient = new IBinder.DeathRecipient() {
@Override
public void binderDied() {
LogUtil.e("bind die");
iBindPoolInterface.asBinder().unlinkToDeath(mBinderPoolDeathRecipient,0);
connectService(mContext);
}
};
public IBinder queryBinder(int requestCode) throws RemoteException{
LogUtil.e("iBindPoolInterface = "+iBindPoolInterface);
if(null != iBindPoolInterface){
return iBindPoolInterface.queryBinder(requestCode);
}
return null;
}
public static class IBindPoolImpl extends IBindPoolInterface.Stub{
@Override
public IBinder queryBinder(int requestCode) throws RemoteException {
IBinder iBinder = null;
switch (requestCode){
case REQUEST_CODE_PLAYMUSIC:
iBinder = new IPlayImpl();
break;
case REQUEST_CODE_DOWNLOAD:
iBinder = new IDownLoadImpl();
break;
}
return iBinder;
}
}
}
下面是IPlayImpl类和IDownLoadImpl的代码:
IPlayImpl.java
import android.os.Process;
import android.os.RemoteException;
import test.cn.example.com.androidskill.IPlayInterface;
import test.cn.example.com.util.LogUtil;
public class IPlayImpl extends IPlayInterface.Stub {
@Override
public void palyMusic(String musicName) throws RemoteException {
LogUtil.e("播放的歌曲是 "+musicName+" Process.myPid()= "+ Process.myPid());
}
}
IDownLoadImpl.java
import android.os.Process;
import android.os.RemoteException;
import test.cn.example.com.androidskill.IDownLoadInterface;
import test.cn.example.com.util.LogUtil;
public class IDownLoadImpl extends IDownLoadInterface.Stub {
@Override
public void downLoad(String url) throws RemoteException {
LogUtil.e("下载的url地址是 "+url+" Process.myPid()= "+ Process.myPid());
}
}
完成了上面的步骤后,就可以在Activity中使用了:
new Thread(new Runnable() {
@Override
public void run() {
try {
// 1
IBinder iPlayBinder = BindPool.getInstance(ChapterTwoActivity.this).queryBinder(1);
LogUtil.e("iPlayBinder = "+iPlayBinder);
if(null != iPlayBinder){
IPlayInterface iPlayInterface = IPlayInterface.Stub.asInterface(iPlayBinder);
iPlayInterface.palyMusic("说好不哭");
}
IBinder iDownLoadBinder = BindPool.getInstance(ChapterTwoActivity.this).queryBinder(2);
LogUtil.e("iDownLoadBinder = "+iDownLoadBinder);
if(null != iDownLoadBinder){
IDownLoadInterface iDownLoadInterface = IDownLoadInterface.Stub.asInterface(iDownLoadBinder);
iDownLoadInterface.downLoad("www.kugo.com");
}
} catch (RemoteException e) {
e.printStackTrace();
}
}
}).start();
总结:上面整个过程是通过一个binder连接池来和一个Service建立连接,连接成功后,会返回一个远程服务端的binder代理对象,这个对象就是BindPool类中的iBindPoolInterface,这样就可以通过iBinderPoolInterface这个远程服务的代理对象,通过queryIBinder方法中传入的不同的requestCode,向远程服务发起queryBinder,这样远程服务端的mBinder对象就会响应queryBinder(int requestCode)方法,由于服务端返回的Binder就是IBindPoolImpl这个对象,所以BindPool类中的IBindPoolImpl的queryBinder(int requestCode)方法就得到执行,再通过请求的requestCode返回一个Binder对象给客户端进程,假设这里返回的是IPlayImpl这个Binder对象,这样客户端进程拿到这个IPlayImpl这个Binder对象的代理后,在通过这个代理来发起请求,后面再次进行进程间通信,最终在服务端会执行IPlayImpl这个Binder中的具体方法,如果这个方法有返回值,就将结果返回给
客户端进程。由于在客户端调用通过BindPool初始化时,也进行了和远程服务进行连接,所以,如果服务端还未和客户端建立连接,那么立刻调用BindPool.getInstance(ChapterTwoActivity.this).queryBinder(1)方法时,可能此时iBindPoolInterface这个对象还是null,所以,为了避免这种情况的出现, 我们在bindService后,通过CountDownLatch这个线程对象的await()方法,将当前线程阻塞,知道和服务端建立了连接后,这样iBindPoolInterface才会赋值,这时,在将取消当前线程的阻塞状态,这样后续的操作才能正常的进行。
上面只是演示了如何使用aidl,生成Binder,进行进程间的通信。下面,从应用层,简要分析下,binder的具体执行过程。
在上面的代码注释1 处,这行代码 IBinder iPlayBinder = BindPool.getInstance(ChapterTwoActivity.this).queryBinder(1);
这样代码会执行BindPool类中的queryBinder方法,
public IBinder queryBinder(int requestCode) throws RemoteException{
LogUtil.e("iBindPoolInterface = "+iBindPoolInterface);
if(null != iBindPoolInterface){
return iBindPoolInterface.queryBinder(requestCode);
}
return null;
}
这个方法里面
iBindPoolInterface.queryBinder(requestCode)就是具体的客户端级进程开始向服务端进程发起的请求的开始处。
由于iBindPoolInterface是服务端进程的Binder对象的一个代理对象,下面看看这个代理对象是什么:
public interface IBindPoolInterface extends android.os.IInterface {
/**
* Local-side IPC implementation stub class.
*/
public static abstract class Stub extends android.os.Binder implements test.cn.example.com.androidskill.IBindPoolInterface {
private static final java.lang.String DESCRIPTOR = "test.cn.example.com.androidskill.IBindPoolInterface";
/**
* Construct the stub at attach it to the interface.
*/
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an test.cn.example.com.androidskill.IBindPoolInterface interface,
* generating a proxy if needed.
*/
public static test.cn.example.com.androidskill.IBindPoolInterface asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof test.cn.example.com.androidskill.IBindPoolInterface))) {
return ((test.cn.example.com.androidskill.IBindPoolInterface) iin);
}
return new test.cn.example.com.androidskill.IBindPoolInterface.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 {
java.lang.String descriptor = DESCRIPTOR;
switch (code) {
case INTERFACE_TRANSACTION: {
reply.writeString(descriptor);
return true;
}
case TRANSACTION_queryBinder: {
data.enforceInterface(descriptor);
int _arg0;
_arg0 = data.readInt();
android.os.IBinder _result = this.queryBinder(_arg0);
reply.writeNoException();
reply.writeStrongBinder(_result);
return true;
}
default: {
return super.onTransact(code, data, reply, flags);
}
}
}
private static class Proxy implements test.cn.example.com.androidskill.IBindPoolInterface {
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 android.os.IBinder queryBinder(int requestCode) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
android.os.IBinder _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(requestCode);
mRemote.transact(Stub.TRANSACTION_queryBinder, _data, _reply, 0);
_reply.readException();
_result = _reply.readStrongBinder();
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
}
static final int TRANSACTION_queryBinder = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
}
public android.os.IBinder queryBinder(int requestCode) throws android.os.RemoteException;
}
这个代理对象其实就是IBindPoolInterface,Stub.Proxy这个类的实例。这个IBindPoolInterface,Stub.Proxy对test.cn.example.com.androidskill.IBindPoolInterface接口中的queryBinder进行了具体的实现,所以,当iBindPoolInterface调用queryBinder方法时,具体就执行到了IBindPoolInterface,Stub.Proxy类中的queryBinder方法,这样 mRemote.transact(Stub.TRANSACTION_queryBinder, _data, _reply, 0);方法就执行了,这里的mRemotej就是一个IBindPoolInterface,Stub,IBindPoolInterface,Stub其实是继承Binder的,所以mRemote对象也就是一个Binder对象,这样就开始通过Binder发起进程间通信了。这个过程可以看下面这个图:图1
上面介绍的过程,就是上面这幅图中Clinet------->远程请求------>Binder----------->Transact这个过程。
具体Transact-------------->Servcie--------------->OnTransact过程,可以参考下面这个图:图2
客户端通过的Binder代理对象发起请求,到mRemote.transact(Stub.TRANSACTION_queryBinder, _data, _reply, 0);后,
服务端的Binder的onTransact方法就执行了,下面看看服务端返回的Binder,通过上面的BindPoolService代码,可以知道,服务端返回的Binder其实就是BindPool.IBindPoolImpl这个对象,这个IBindPoolImpl类是继承IBindPoolInterface.Stub,所以,服务端的onTransact方法的执行,就是调用了IBindPollImpl这个Binder的onTransact方法,也就是其父类IBindPoolInterface.Stub类中的onTransact方法:
@Override
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
java.lang.String descriptor = DESCRIPTOR;
switch (code) {
case INTERFACE_TRANSACTION: {
reply.writeString(descriptor);
return true;
}
case TRANSACTION_queryBinder: {
data.enforceInterface(descriptor);
int _arg0;
_arg0 = data.readInt();
// 关键代码
android.os.IBinder _result = this.queryBinder(_arg0);
reply.writeNoException();
reply.writeStrongBinder(_result);
return true;
}
default: {
return super.onTransact(code, data, reply, flags);
}
}
}
这个方法内部,最后会调用 this.queryBinder(_arg0),这个方法其实最终会调用到BindPool.IBindPoolImpl类的queryBinder方法
public static class IBindPoolImpl extends IBindPoolInterface.Stub{
@Override
public IBinder queryBinder(int requestCode) throws RemoteException {
IBinder iBinder = null;
switch (requestCode){
case REQUEST_CODE_PLAYMUSIC:
iBinder = new IPlayImpl();
break;
case REQUEST_CODE_DOWNLOAD:
iBinder = new IDownLoadImpl();
break;
}
return iBinder;
}
}
这个方法最终会根据请求的requestCode返回相应的Binder对象给客户端。这就是整个Binder的进程间通信的过程。