Android 内核 - 01 Binder
来源:互联网 发布:禁止xp下载 安装软件 编辑:程序博客网 时间:2024/06/07 00:51
Binder 概述
Binder是一种架构,一种进程间通信(IPC)的机制,它工作在Linux内核层面,属于驱动层的一个模块。
但它其实并不是与硬件打交道,是上层消息转发的一个通道。工作在内核层效率更高。
Binder的应用
在这种架构中有三个模块,服务端接口,Binder驱动,客户端接口。
服务端接口:是Binder的一个对象,向客户端提供服务,通过重载onTransact()接口来实现业务。
Binder驱动:当创建一个服务Binder对象后,它同时会在Binder驱动中创建一个Binder的mRemote对象。
当客户端需要Binder服务时,都是通过mRemote对象来获得的。这是一种代理方式。
客户端接口:客户端需要获取服务,必须获取远程服务的代理的引用。客户端实现自己的业务时可以获得服务端支持。
一个简单的Binder应用的实例
实例分为两部分 Server App 和 Client App,是两个独立的App程序。
Client会绑定一个Server的Service,将当前时间传递给Server,Server端收到后,再将它的时间添加在后面
返回给Client端。
Server 端
一个普通的Service类,其中包含了一个Binder子类。其中 Binder子类重载了onTransact函数用于处理Client端过来的请求。
public class SampleService extends Service{ private static final String TAG = "BINDServer"; private static final String DESCRIPTOR = "TESTING"; public ServiceBinder mBinder = new ServiceBinder(); private static int m_CallingTimes = 0; @Override public void onCreate() { Log.d(TAG, "SampleService::onCreate()"); super.onCreate(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.d(TAG, "SampleService::onStartCommand()"); return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { Log.d(TAG, "SampleService::onDestroy()"); super.onDestroy(); } @Override public IBinder onBind(Intent arg0) { return mBinder; } public class ServiceBinder extends Binder { protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { Log.d(TAG, "ServiceBinder::onTransact() code=" + code); String strResult = ""; switch (code) { case 0x01: { data.enforceInterface(DESCRIPTOR); String _arg0; _arg0 = data.readString(); strResult = getInfo(_arg0, "===>"); reply.writeNoException(); reply.writeString(strResult); Log.d(TAG, "ServiceBinder::onTransact() result=" + strResult); return true; } default: break; } return super.onTransact(code, data, reply, flags); } public String getInfo(String strRecv, String strCode) { Date date = new Date(); String strResult = new String(date.toString()); strResult = m_CallingTimes + "::" + strRecv + strCode + strResult; return strResult; } }}
Client 端
一个普通的Activity,它取得当前时间,并将当前时间的字符串打包发给Server端。
1) 它通过bindService函数取得了Server端Binder的对象。
public void bindService(View view)
{
Log.d(TAG, "bindService");
Intent intent = new Intent();
intent.setAction("com.example.bindersample.TestInterface");
boolean bindFlag = bindService(intent, mServiceConn, Context.BIND_AUTO_CREATE);
Log.e(TAG, "bindService() = " + bindFlag);
}
Clinet端函数中通过setAction指定 <intent-filter> = com.example.bindersample.TestInterface
这个Inter-filter是定义在Server端的AndroidManifest.xml中,定义了这个action android:name,系统就知道如何查找了
<service android:name="SampleService">
<intent-filter>
<action android:name="com.example.bindersample.TestInterface" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</service>
2) 当Client取得了Binder对象后,可以调用它的 transact() 接口,来使用Service的服务了
boolean android.os.IBinder.transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException
关于参数的简单说明
int code:可以通过code告诉Server端提供不同类型的服务
Parcel data:传递给Server端的参数
Parcel reply:从Server端返回的参数
int flags:0 表示当前的操作是一个普通的RPC,如果是1 (ONE_WAY),则表示是一个one way 的RPC。
public class MainActivity extends Activity { private static final String TAG = "BinderClient"; private IBinder mBinder; private ServiceConnection mServiceConn = new ServiceConnection() { @Override public void onServiceDisconnected(ComponentName name) { Log.d(TAG, "mServiceConn onServiceDisconnected"); } @Override public void onServiceConnected(ComponentName name, IBinder service) { Log.d(TAG, "mServiceConn onServiceConnected"); mBinder = service; } }; public void bindService(View view) { Log.d(TAG, "bindService"); Intent intent = new Intent(); intent.setAction("com.example.bindersample.TestInterface"); boolean bindFlag = bindService(intent, mServiceConn, Context.BIND_AUTO_CREATE); Log.e(TAG, "bindService() = " + bindFlag); } public void unbindService(View view) { unbindService(mServiceConn); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } public void testClick(View view) { if (mBinder == null) { Log.d(TAG, "testClick() mBinder is NULL"); } else { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); String _result; try { Date date = new Date(); _data.writeInterfaceToken("TESTING"); _data.writeString(date.toString()); mBinder.transact(0x01, _data, _reply, 0); _reply.readException(); _result = _reply.readString(); Toast.makeText(this, _result + "", Toast.LENGTH_SHORT).show(); } catch (RemoteException e) { e.printStackTrace(); } finally { _reply.recycle(); _data.recycle(); } } } }
Binder运行的基本流程
- 获取Binder对象
1) Server端的Service需要被启动,并且Server端的Binder对象实现了public IBinder onBind(Intent arg0) 接口
可以将它的Binder对象提供给外部。
2) Client端需要调用bindService接口,来获取Server端的Binder对象的引用。
public void bindService(View view) { Log.d(TAG, "bindService"); Intent intent = new Intent(); intent.setAction("com.example.bindersample.TestInterface"); boolean bindFlag = bindService(intent, mServiceConn, Context.BIND_AUTO_CREATE); Log.e(TAG, "bindService() = " + bindFlag); }
public boolean bindService (Intent service, ServiceConnection conn, int flags)
Intent service:指定Client端需要的Service, 系统通过intent.setAction("com.example.bindersample.TestInterface");
中的名字会找到指定的Service。
而Client端指定的这个Action name是在Server端的AndroidManifest.xml中定义的。
<service android:name="SampleService"> <intent-filter> <action android:name="com.example.bindersample.TestInterface" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </service>
ServiceConnection conn:它的两个接口是由系统进行回调的,主要是当Service 连接后和断开后会被执行。
private ServiceConnection mServiceConn = new ServiceConnection()
{
@Override
public void onServiceDisconnected(ComponentName name)
{ }
@Override
public void onServiceConnected(ComponentName name, IBinder service)
{ }
};
在实例程序中,当Client与Server连接后,在onServiceConnected接口中可以取得Server端Binder的引用。
- Client 与 Server交互
1) Client 组织好数据包裹后,调用 Binder引用的transact方法
2) 他会通知 Binder Driver有消息需要传递了,Binder会阻塞当前的Client线程
3) Binder Driver会找到Server的远程对象,并将Client的数据包裹传递给Server
4) Server收到通知,在onTransact中可以对包裹进行处理,如果需要也可以将处理后的数据再返回Client端。
5) Server处理完成后,通知Binder Driver,Binder Driver会使客户端线程得以返回,并继续以运行。
关于 android.os.Parcel
它是Server端和Client端用来传递数据的包裹
1) 获得包裹 android.os.Parcel.obtain();
Retrieve a new Parcel object from the pool. 使用pool的方式效率一定是比创建/释放的方式要高许多。
2) 接口名字 android.os.Parcel.enforceInterface(String interfaceName) 和
android.os.Parcel.writeInterfaceToken(String interfaceName)
可以通过这两个接口来为包裹设置名字,以保证他们在同一个Session中。
3) 拆包裹 android.os.Parcel.readString();
这里当然不光是String,还可以readInt,readDouble等等,可以根据封包的顺序来拆包。
注意: 关于 readException();
API的解释 :
Special function for reading an exception result from the header of a parcel, to be used after receiving the result of a transaction. This will throw the exception for you if it had been written to the Parcel, otherwise return and let you read the normal result data from the Parcel.
4) 封包裹 android.os.Parcel.writeString();
这里当然不光是String,还可以Int,Double等等,与拆包对应。
0 0
- Android 内核 - 01 Binder
- 2.Android内核 Binder
- Android内核剖析:Binder
- Android内核剖析之Binder
- android内核剖析 binder读书笔记
- Android内核学习之Binder
- Android 内核--Binder架构分析
- Android 内核--Binder架构分析
- Android 内核--Binder架构分析
- android内核剖析之Binder篇(应用服务中Binder)
- Binder Android IPC Linux 内核 驱动
- 学习笔记--《android内核剖析》binder
- 读书笔记---《android内核剖析》之Binder
- 学习android内核-Binder笔记
- Binder Android IPC Linux 内核 驱动
- android Binder Linux IPC 内核 驱动
- Android内核学习笔记—Binder分析
- android中的Binder(android内核学习记录)
- jsp 导航栏显示日期和星期几
- PPTController --第一次github尝试
- 第三周项目10-小学生计算题的随机生成
- iOS的单例模式
- struts2获得原始request、response、session的两种方法
- Android 内核 - 01 Binder
- IMMNotificationClient interface(MSDN理解)
- 使用递归实现全排列输出
- [bzoj2965]保护古迹
- C# 类型基础
- JAVA流程控制语句
- 阿里电话二面总结
- 当电商遇到SaaS 会有怎样的火花
- PAT (Advanced Level) Practise 1064 Complete Binary Search Tree (30)