android service aidl 理解
2014-03-22 23:19
260 查看
参考:http://developer.android.com/guide/components/aidl.html
http://developer.android.com/guide/topics/manifest/service-element.html
service 属性基础
View Code
分析:
类结构:
接口ISecondary{
抽象类Stub 继承 Binder 实现 ISecondary{
类Proxy 实现Isecondary{
}
}
}
在Activity SeviceConnect 调用 ISencond.stub.asInteface 接口获取ISencond实例 分析 asInteface方法:
查询是本地调用直接返回stub,如果是远程调用返回代理类Proxy。
至于以后调用如:mSecondaryService.getPid(),basicTypes等,本地调用直接返回实现stup抽象函数实现的方法体,远程调用看Proxy中的实现的函数。
1.将参数实例化Parcel(_data)对象,传递到Binder驱动。让客户端进程休眠,并且将传过来的pacel数据从客户端进程映射到服务端进程。
2.服务端线程调用ontransact方法解包执行相应方法操作并将返回值写入parcel(_reply)。
3.服务端线程将返回值传递给binder驱动,binder驱动重新唤醒客户端进程并把返回值传递给proxy对象,会被调用并最后被解包并作为proxy方法的返回值。
说明:
1.来自本地进程的调用会在与调用者相同的线程中被执行。如果这是主UI线程,那么线程会在AIDL接口中继续执行。如果是另外一个线程,那么调用例程是在服务中要执行代码之一。因此,只有正在访问服务的本地线程,才能够完全控制调用会在哪个线程中执行(但是,这个中情况下,完全不需要使用AIDL,而是应该通过实现Binder来创建接口)。
2.来自远程进程的调用会被分配到一个由平台维护的进程内部的线程池中。你必须为来自未知的、同时发生的多次调用的线程做好准备。换句话说,AIDL接口的实现必须是线程安全的。
3.oneway关键词是用来修饰远程调用行为的。当使用该关键词时,远程调用不是阻塞的,它只是发送事物数据并立即返回。接口的实现最终实现是把普通的远程调用按照Binder线程池的调用规则来接收的。如果oneway是使用在本地调用上,那么不会有任何影响,并且调用依然是同步的
http://developer.android.com/guide/topics/manifest/service-element.html
service 属性基础
public interface ISecondary extends android.os.IInterface { /** Local-side IPC implementation stub class. */ public static abstract class Stub extends android.os.Binder implements com.example.android.apis.app.ISecondary { private static final java.lang.String DESCRIPTOR = "com.example.android.apis.app.ISecondary"; /** Construct the stub at attach it to the interface. */ public Stub() { this.attachInterface(this, DESCRIPTOR); } /** * Cast an IBinder object into an * com.example.android.apis.app.ISecondary interface, generating a proxy * if needed. */ public static com.example.android.apis.app.ISecondary asInterface( android.os.IBinder obj) { if ((obj == null)) { return null; } android.os.IInterface iin = (android.os.IInterface) obj .queryLocalInterface(DESCRIPTOR); if (((iin != null) && (iin instanceof com.example.android.apis.app.ISecondary))) { return ((com.example.android.apis.app.ISecondary) iin); } return new com.example.android.apis.app.ISecondary.Stub.Proxy(obj); } 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_getPid: { data.enforceInterface(DESCRIPTOR); int _result = this.getPid(); reply.writeNoException(); reply.writeInt(_result); return true; } case TRANSACTION_basicTypes: { data.enforceInterface(DESCRIPTOR); int _arg0; _arg0 = data.readInt(); long _arg1; _arg1 = data.readLong(); boolean _arg2; _arg2 = (0 != data.readInt()); float _arg3; _arg3 = data.readFloat(); double _arg4; _arg4 = data.readDouble(); java.lang.String _arg5; _arg5 = data.readString(); this.basicTypes(_arg0, _arg1, _arg2, _arg3, _arg4, _arg5); reply.writeNoException(); return true; } } return super.onTransact(code, data, reply, flags); } private static class Proxy implements com.example.android.apis.app.ISecondary { private android.os.IBinder mRemote; Proxy(android.os.IBinder remote) { mRemote = remote; } public android.os.IBinder asBinder() { return mRemote; } public java.lang.String getInterfaceDescriptor() { return DESCRIPTOR; } /** * Request the PID of this service, to do evil things with it. */ public int getPid() throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); int _result; try { _data.writeInterfaceToken(DESCRIPTOR); mRemote.transact(Stub.TRANSACTION_getPid, _data, _reply, 0); _reply.readException(); _result = _reply.readInt(); } finally { _reply.recycle(); _data.recycle(); } return _result; } /** * This demonstrates the basic types that you can use as parameters * and return values in AIDL. */ public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, java.lang.String aString) throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); try { _data.writeInterfaceToken(DESCRIPTOR); _data.writeInt(anInt); _data.writeLong(aLong); _data.writeInt(((aBoolean) ? (1) : (0))); _data.writeFloat(aFloat); _data.writeDouble(aDouble); _data.writeString(aString); mRemote.transact(Stub.TRANSACTION_basicTypes, _data, _reply, 0); _reply.readException(); } finally { _reply.recycle(); _data.recycle(); } } } static final int TRANSACTION_getPid = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0); static final int TRANSACTION_basicTypes = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1); } /** * Request the PID of this service, to do evil things with it. */ public int getPid() throws android.os.RemoteException; /** * This demonstrates the basic types that you can use as parameters and * return values in AIDL. */ public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, java.lang.String aString) throws android.os.RemoteException; }
View Code
分析:
类结构:
接口ISecondary{
抽象类Stub 继承 Binder 实现 ISecondary{
类Proxy 实现Isecondary{
}
}
}
在Activity SeviceConnect 调用 ISencond.stub.asInteface 接口获取ISencond实例 分析 asInteface方法:
public static com.example.android.apis.app.ISecondary asInterface( android.os.IBinder obj) { if ((obj == null)) { return null; } android.os.IInterface iin = (android.os.IInterface) obj .queryLocalInterface(DESCRIPTOR); if (((iin != null) && (iin instanceof com.example.android.apis.app.ISecondary))) { return ((com.example.android.apis.app.ISecondary) iin); } return new com.example.android.apis.app.ISecondary.Stub.Proxy(obj); }
查询是本地调用直接返回stub,如果是远程调用返回代理类Proxy。
至于以后调用如:mSecondaryService.getPid(),basicTypes等,本地调用直接返回实现stup抽象函数实现的方法体,远程调用看Proxy中的实现的函数。
1.将参数实例化Parcel(_data)对象,传递到Binder驱动。让客户端进程休眠,并且将传过来的pacel数据从客户端进程映射到服务端进程。
2.服务端线程调用ontransact方法解包执行相应方法操作并将返回值写入parcel(_reply)。
3.服务端线程将返回值传递给binder驱动,binder驱动重新唤醒客户端进程并把返回值传递给proxy对象,会被调用并最后被解包并作为proxy方法的返回值。
说明:
1.来自本地进程的调用会在与调用者相同的线程中被执行。如果这是主UI线程,那么线程会在AIDL接口中继续执行。如果是另外一个线程,那么调用例程是在服务中要执行代码之一。因此,只有正在访问服务的本地线程,才能够完全控制调用会在哪个线程中执行(但是,这个中情况下,完全不需要使用AIDL,而是应该通过实现Binder来创建接口)。
2.来自远程进程的调用会被分配到一个由平台维护的进程内部的线程池中。你必须为来自未知的、同时发生的多次调用的线程做好准备。换句话说,AIDL接口的实现必须是线程安全的。
3.oneway关键词是用来修饰远程调用行为的。当使用该关键词时,远程调用不是阻塞的,它只是发送事物数据并立即返回。接口的实现最终实现是把普通的远程调用按照Binder线程池的调用规则来接收的。如果oneway是使用在本地调用上,那么不会有任何影响,并且调用依然是同步的
相关文章推荐
- Android系统中aidl的理解和service的添加
- 深入理解Android的startservice和bindservice
- Android AIDL 与 Service
- Android中BindService方式使用的理解
- Android用AIDL创建Service
- android中service和aidl详细整理
- android 中activity调用远程service中的方法之 aidl的使用
- 深入理解Android的startservice和bindservice
- 基于Socket的TCP长连接(服务端Java+客户端Android),Service配合AIDL实现
- Android Service AIDL
- Android Service总结06 之AIDL
- Android AIDL Service 跨进程传递复杂数据
- Android-AIDL,service,Binder,Bundles,Messenger,transact()与onTransact()函数
- Android远程service aidl的用法
- android中对Looper、HandlerThread、IntentService的理解及使用方法
- Android Service与AIDL的使用
- 使用android中的AIDL让Service与Activity通信(service回调activity)
- 为 Android 添加 Java 层服务也就是添加自定义的aidl服务到serviceManager 通过ServiceManager.getService取
- Android Service学习之AIDL, Parcelable和远程服务
- Android中BindService方式使用的理解