Binder概念
1 机制 Binder是一种Android中实现跨进程通信(IPC)的方式
2 从组成,设备来说,什么是Binder Binder还是一种虚拟的物理设备驱动 /dev/binder
3 从Android代码来说 BInder 是一个类,实现了IBinder接口
可以这么理解AIDL和Binder的关系:
AIDL:是定义的一种通信规范
BInder:是一种具体的通信媒介
跨进程通信方式实现:
服务端
第一步:
创建一个服务Service,返回一个IBinder对象
public class MyService extends Service {
@Override
public void onCreate() {super.onCreate();}
/**
* 提供给客户端
*/
@Nullable
@Override
public IBinder onBind(Intent intent) {
//MyApp myApp;
return new MyAppIml();
}
}
第二步:创建一个AIDL文件
aild文件其实是一个模板类,系统会根据这个模板自动生成别的java代码
//接口里只能定义基本的数据类型
interface MyApp {
String getName();
String setName(String name);
}
第三步:build工程,系统会自动生成一些java代码
客户端
1.将服务端提供的AIDL文件和aild所在的包,拷贝到客户端工程
2.build编译
- 在需要和服务端通信的地方调用bindService ,重写ServiceConnection对象的onServiceConnected方法,参数中的ibinder即为服务端传递过来的IBinder对象,这样便可以完成跨进程间的通信。
public void load(View view) {
Intent intent = new Intent();
intent.setAction("com.example.baby.binderframwork.MyService");
intent.setPackage("com.example.baby.binderframwork");
//进程B 目的 binderServise -----> IBinder iBinder
// c.conn.connected(r.name, service);
bindService(intent, new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
//proxy 装煤炭 Proxy 对象 MyApp接口
MyApp myApp= MyApp.Stub.asInterface(iBinder);
try {
myApp.setName("xxx");
Toast.makeText(MainActivity.this, "---> " + myApp.getName(), Toast.LENGTH_SHORT).show();
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
}
}, Context.BIND_AUTO_CREATE);
}
查看通过aild文件生成的对应的java文件发现该接口继承android.os.IInterface
public interface MyApp extends android.os.IInterface {
/**
* Stub表示接收方
*/
public static abstract class Stub extends android.os.Binder implements com.example.baby.binderframwork.MyApp {
private static final java.lang.String DESCRIPTOR = "com.example.baby.binderframwork.MyApp";
/**
* DESCRIPTOR相当于一个进程的id或tag
*/
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
public static com.example.baby.binderframwork.MyApp asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
//根据DESCRIPTOR查询是否在同一个进程
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof com.example.baby.binderframwork.MyApp))) {
return ((com.example.baby.binderframwork.MyApp) iin);
}
//不在同一个进程则返回Proxy对象(Proxy implement MyApp)
return new com.example.baby.binderframwork.MyApp.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_getName: {
data.enforceInterface(DESCRIPTOR);
java.lang.String _result = this.getName();
reply.writeNoException();
reply.writeString(_result);
return true;
}
case TRANSACTION_setName: {
data.enforceInterface(DESCRIPTOR);
java.lang.String _arg0;
_arg0 = data.readString();
java.lang.String _result = this.setName(_arg0);
reply.writeNoException();
reply.writeString(_result);
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
//Proxy表示发送方
private static class Proxy implements com.example.baby.binderframwork.MyApp {
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 java.lang.String getName() throws android.os.RemoteException {
//Parcel写入另一个进程的参数,类似于一个缓存区,用来保存传递的数据(要访问的类)
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
java.lang.String _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
//调用另一个进程即Binder进程 会调用Binder中的onTransact方法
// TRANSACTION_getName参数为调用哪个方法(int类型)
mRemote.transact(Stub.TRANSACTION_getName, _data, _reply, 0);
_reply.readException();
_result = _reply.readString();
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
@Override
public java.lang.String setName(java.lang.String name) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
java.lang.String _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeString(name);
mRemote.transact(Stub.TRANSACTION_setName, _data, _reply, 0);
_reply.readException();
_result = _reply.readString();
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
}
static final int TRANSACTION_getName = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_setName = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
}
public java.lang.String getName() throws android.os.RemoteException;
public java.lang.String setName(java.lang.String name) throws android.os.RemoteException;
}
我们再来看下Binder的transact方法
Binder.java
public final boolean transact(int code, Parcel data, Parcel reply,
int flags) throws RemoteException {
if (false) Log.v("Binder", "Transact: " + code + " to " + this);
//将数据写入流
if (data != null) {
data.setDataPosition(0);
}
//调用onTransact方法 进入系统进程
boolean r = onTransact(code, data, reply, flags);
if (reply != null) {
reply.setDataPosition(0);
}
return r;
}
客户端给服务端发送消息:
image.png
再来看下客户端绑定服务(bindService())时的经过:
bindService()方法的真正实现类为ContextImpl,看源码
ContextWrapper.java
@Override
public boolean bindService(Intent service, ServiceConnection conn,
int flags) {
return
//mBase为Context
//bindService 真的实现为ContextImpl
mBase.bindService(service, conn, flags);
}
ContextImpl.java
@Override
public boolean bindService(Intent service, ServiceConnection conn,
int flags) {
warnIfCallingFromSystemProcess();
return bindServiceCommon(service, conn, flags, Process.myUserHandle());
}
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags,
UserHandle user) {
IServiceConnection sd;
.......
//ActivityManagerNative.getDefault()的类型为IActivityManager
//IActivityManager extends IInterface 类似于AIDL接口
//ActivityManagerNative extends Binder implements IActivityManager 类似于Stub
//ActivityManagerProxy implements IActivityManager 类似于Proxy
//class ActivityManagerService extends ActivityManagerNative
//调用ActivityManagerProxy的bindService
int res = ActivityManagerNative.getDefault().bindService(
mMainThread.getApplicationThread(), getActivityToken(), service,
service.resolveTypeIfNeeded(getContentResolver()),
sd, flags, getOpPackageName(), user.getIdentifier());
.....
}
ActivityManagerProxy.java
ActivityManagerProxy implements IActivityManager 类似于Proxy
public int bindService(IApplicationThread caller, IBinder token,
Intent service, String resolvedType, IServiceConnection connection,
int flags, String callingPackage, int userId) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(caller != null ? caller.asBinder() : null);
data.writeStrongBinder(token);
service.writeToParcel(data, 0);
data.writeString(resolvedType);
data.writeStrongBinder(connection.asBinder());
data.writeInt(flags);
data.writeString(callingPackage);
data.writeInt(userId);
//调用另一个进程即Binder进程 会调用Binder中的onTransact方法
mRemote.transact(BIND_SERVICE_TRANSACTION, data, reply, 0);
reply.readException();
int res = reply.readInt();
data.recycle();
reply.recycle();
return res;
}
ActivityManagerNative.java
ActivityManagerNative extends Binder implements IActivityManager 类似于Stub
@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
.....
case BIND_SERVICE_TRANSACTION: {
...
//调用ActivityManagerService的bindService
int res = bindService(app, token, service, resolvedType, conn, fl,
callingPackage, userId);
...
return true;
}
ActivityManagerService.java
ActivityManagerService extends ActivityManagerNative
ActivityManagerNative extends Binder implements IActivityManager 类似于Stub
public int bindService(IApplicationThread caller, IBinder token, Intent service,
String resolvedType, IServiceConnection connection, int flags, String callingPackage,
int userId) throws TransactionTooLargeException {
.....
synchronized(this) {
//调用ActiveServices的bindServiceLocked
return mServices.bindServiceLocked(caller, token, service,
resolvedType, connection, flags, callingPackage, userId);
}
}
ActiveServices.java
int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
String resolvedType, IServiceConnection connection, int flags,
String callingPackage, int userId) throws TransactionTooLargeException {
....
final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
...//检查调用者是否存在....
AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
//创建ConnectionRecord
ConnectionRecord c = new ConnectionRecord(b, activity,
connection, flags, clientLabel, clientIntent);
//得到IBinder对象,就是要回调给客户端的IBinder对象
//并添加到集合保存
IBinder binder = connection.asBinder();
ArrayList<ConnectionRecord> clist = s.connections.get(binder);
if (clist == null) {
clist = new ArrayList<ConnectionRecord>();
s.connections.put(binder, clist);
}
clist.add(c);
b.connections.add(c);
if (activity != null) {
if (activity.connections == null) {
activity.connections = new HashSet<ConnectionRecord>();
}
activity.connections.add(c);
}
b.client.connections.add(c);
if ((c.flags&Context.BIND_ABOVE_CLIENT) != 0) {
b.client.hasAboveClient = true;
}
if (s.app != null) {
updateServiceClientActivitiesLocked(s.app, c, true);
}
clist = mServiceConnections.get(binder);
if (clist == null) {
clist = new ArrayList<ConnectionRecord>();
mServiceConnections.put(binder, clist);
}
clist.add(c);
...进行四种情况判断...
//1.整个进程B没有启动()
//2.进程有了但Service没有创建(执行ActivityThread的scheduleCreateService)
//3.进程有了Service创建了但没有被客户端绑定(执行ActivityThread的scheduleBindService)
//4.进程有了Service创建了已经被其他客户端绑定 (执行onRebind)
...
}
ActivityThread.java
public final void scheduleCreateService(IBinder token,
ServiceInfo info, CompatibilityInfo compatInfo, int processState) {
...
//发送给Hander
sendMessage(H.CREATE_SERVICE, s);
}
public final void scheduleBindService(IBinder token, Intent intent,
boolean rebind, int processState) {
.....
//发送给Hander
sendMessage(H.BIND_SERVICE, s);
}
H.java extends Handler
private void handleCreateService(CreateServiceData data) {
// If we are getting ready to gc after going to the background, well
// we are back active so skip it.
unscheduleGcIdler();
LoadedApk packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo, data.compatInfo);
Service service = null;
try {
//重要的地方,可以替换为我们的DexClassLoader干别的
java.lang.ClassLoader cl = packageInfo.getClassLoader();
//反射的方式创建Service
service = (Service) cl.loadClass(data.info.name).newInstance();
} catch (Exception e) {
if (!mInstrumentation.onException(service, e)) {
throw new RuntimeException(
"Unable to instantiate service " + data.info.name
+ ": " + e.toString(), e);
}
}
try {
if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);
ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
context.setOuterContext(service);
Application app = packageInfo.makeApplication(false, mInstrumentation);
//调用Service生命周期中的attach方法
service.attach(context, this, data.info.name, data.token, app,
ActivityManagerNative.getDefault());
//调用Service生命周期中的onCreate方法
service.onCreate();
mServices.put(data.token, service);
try {
ActivityManagerNative.getDefault().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
} catch (RemoteException e) {
// nothing to do.
}
} catch (Exception e) {
if (!mInstrumentation.onException(service, e)) {
throw new RuntimeException(
"Unable to create service " + data.info.name
+ ": " + e.toString(), e);
}
}
}
private void handleBindService(BindServiceData data) {
Service s = mServices.get(data.token);
if (DEBUG_SERVICE)
Slog.v(TAG, "handleBindService s=" + s + " rebind=" + data.rebind);
if (s != null) {
try {
data.intent.setExtrasClassLoader(s.getClassLoader());
data.intent.prepareToEnterProcess();
try {
if (!data.rebind) {
//重点 调用service的onBind方法返回IBinder对象
IBinder binder = s.onBind(data.intent);
//发送给客户端
ActivityManagerNative.getDefault().publishService(
data.token, data.intent, binder);
} else {
s.onRebind(data.intent);
ActivityManagerNative.getDefault().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
}
ensureJitEnabled();
} catch (RemoteException ex) {
}
} catch (Exception e) {
if (!mInstrumentation.onException(s, e)) {
throw new RuntimeException(
"Unable to bind to service " + s
+ " with " + data.intent + ": " + e.toString(), e);
}
}
}
}
Binder核心机制
Binder核心机制.png
网友评论