Binder不用多说,Android的核心机制之一,用于进程间通信,更加安全,只进行一次拷贝数据。
1.创建aidl文件
package com.example.davidzhaodz.myapplication;
// 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);
void add(int a, int b); //这个是你要使用的函数
}
2.创建service,这里面实现了add。IMyAidlInterface.Stub是as编译aidl文件自动生成的
public class TestService extends Service {
@Nullable
@Override
public IBinder onBind(Intent intent) {
return mIBinder;
}
private final IBinder mIBinder = new IMyAidlInterface.Stub() {
@Override
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
}
@Override
public void add(int a, int b) throws RemoteException {
Log.e("david", "test add - remote");
}
};
}
3.关于自动生成的IMyAidlInterface.java
主要有两个内部类Stub和Proxy,其实这两个类是真正用于binder通信的。多说两句,其实client对server的访问时分两种的,一种是在同一个进程,这时候binder直接通信,不需要代理。第二种是,在不同的进程,这时server端的是binder的代理,是真的要通过binder驱动进行跨进程通信了
public static com.example.davidzhaodz.myapplication.IMyAidlInterface asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.example.davidzhaodz.myapplication.IMyAidlInterface))) {
return ((com.example.davidzhaodz.myapplication.IMyAidlInterface)iin);//本地接口
}
return new com.example.davidzhaodz.myapplication.IMyAidlInterface.Stub.Proxy(obj);//返回代理
}
其实这里些播放器用aidl。有人说是大炮打蚊子,其实只是看起来大炮打蚊子,实际逻辑并不是这样,因为有这样的逻辑判断
4.在你的activity里bindservice,调用函数。别忘了service添加到manifest
private void testService() {
Log.e("david", "testService");
Intent intent = new Intent(this, TestService.class);
bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
}
private IMyAidlInterface mIMyAidlInterface;
private ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mIMyAidlInterface = IMyAidlInterface.Stub.asInterface(service);
try {
mIMyAidlInterface.add(3, 4);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
一个基本的binder调用就基本完成了
题外话:
1.service为什么有onBind,想了想,其实service就是通过binder来进行通信的,可以跨进程,可以是同一个进程
2.不用aidl怎么实现。看一下IMyAidlInterface.java,就知道了。最主要的Stub,就是继承了Binder,实现了接口。如果自己来写,也只要继承Binder,实现接口,同时注意需要实现onTransact,是最重要的。这里有个重要区别,本地Binder是onTranscat,而代理调用Trancat,也就是说onTrancat是在服务端的(返回数据),Trancat是在客户端(发送数据)。看代码理解。
3.从framework来说,应用调用系统服务,wms/ams/ims都是跨进程调用,因为这些系统服务是属于systemserver的.同样看源码可以知道,这些系统服务都是按照binder调用来写的,而且为了便于app调用,framework有时把client端的接口实现也写好了,所以有时我们调用起来,感觉不到binder
网上有个不错的例子 https://github.com/yuanhuihui/BinderSample 他把app/framework/native都谢了例子