- CompoundButton 源码分析
- LinearLayout 源码分析
- SearchView 源码解析
- LruCache 源码解析
- ViewDragHelper 源码解析
- BottomSheets 源码解析
- Media Player 源码分析
- NavigationView 源码解析
- Service 源码解析
- Binder 源码分析
- Android 应用 Preference 相关及源码浅析 SharePreferences 篇
- ScrollView 源码解析
- Handler 源码解析
- NestedScrollView 源码解析
- SQLiteOpenHelper/SQLiteDatabase/Cursor 源码解析
- Bundle 源码解析
- LocalBroadcastManager 源码解析
- Toast 源码解析
- TextInputLayout
- LayoutInflater 和 LayoutInflaterCompat 源码解析
- TextView 源码解析
- NestedScrolling 事件机制源码解析
- ViewGroup 源码解析
- StaticLayout 源码分析
- AtomicFile 源码解析
- AtomicFile 源码解析
- Spannable 源码分析
- Notification 之 Android 5.0 实现原理
- CoordinatorLayout 源码分析
- Scroller 源码解析
- SwipeRefreshLayout 源码分析
- FloatingActionButton 源码解析
- AsyncTask 源码分析
- TabLayout 源码解析
2.3 远程服务的获取与使用
客户端要使用远程服务,需要绑定服务 ( bindService ) 并建立服务连接 ( ServiceConnection )。
// MainActivity.java public class MainActivity extends AppCompatActivity { private ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { IRemoteService remoteService = IRemoteService.Stub.asInterface(service); try { remoteService.addUser(new User(1, "neo")); } catch (RemoteException e) { e.printStackTrace(); } } ... }; ... @Override protected void onCreate(Bundle savedInstanceState) { ... Intent intent = new Intent().setComponent(new ComponentName( "org.xdty.remoteservice", "org.xdty.remoteservice.RemoteService")); bindService(intent, mConnection, Context.BIND_AUTO_CREATE); } }
我们可以看出,客户端通过 binderService()
方法,获取远程服务并在服务连接 ServiceConnection
中 onServiceConnected()
回调中得到了 IBinder service
实例, 最后通过上文提到的 IRemoteService.Stub.asInterface(service)
方法得到远程服务 IRemoteService
的实例。通过 IRemoteService.addUser()
方法我们可以像调用本地方法一样调用远程方法。在来看 IRemoteService.addUser()
的实现:
// IRemoteService.java public static org.xdty.remoteservice.IRemoteService asInterface(android.os.IBinder obj) { ... return new org.xdty.remoteservice.IRemoteService.Stub.Proxy(obj); } private static class Proxy implements org.xdty.remoteservice.IRemoteService { private android.os.IBinder mRemote; Proxy(android.os.IBinder remote) { mRemote = remote; } @Override public android.os.IBinder asBinder() { return mRemote; } ... @Override public void addUser(org.xdty.remoteservice.User user) throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); try { _data.writeInterfaceToken(DESCRIPTOR); if ((user != null)) { _data.writeInt(1); user.writeToParcel(_data, 0); } else { _data.writeInt(0); } mRemote.transact(Stub.TRANSACTION_addUser, _data, _reply, 0); _reply.readException(); } finally { _reply.recycle(); _data.recycle(); } } }
可以看到客户端调用 remoteService.addUser(new User(1, "neo")) 方法实际上是通过 IBinder service 实例的 transact() 方法,发送了与服务端约定好的命令 Stub.TRANSACTION_addUser
,并将参数按格式打包进 Parcel 对象。
服务端则在 onTransact() 方法中收到命令后会对命令和参数重新解析:
// IRemoteService.java public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException { switch (code) { ... case TRANSACTION_addUser: { data.enforceInterface(DESCRIPTOR); org.xdty.remoteservice.User _arg0; if ((0 != data.readInt())) { _arg0 = org.xdty.remoteservice.User.CREATOR.createFromParcel(data); } else { _arg0 = null; } this.addUser(_arg0); reply.writeNoException(); return true; } } return super.onTransact(code, data, reply, flags); }
可以看到在 onTransact()
中,最终 this.addUser(_arg0) 调用了上文提到的服务端的实现 IRemoteService.Stub.addUser() 。
远程 Binder 对象 mRemote 是由客户端绑定服务时 onServiceConnected() 返回的。继续追踪 bindService()
// ContextImpl.java @Override public boolean bindService(Intent service, ServiceConnection conn, int flags) { warnIfCallingFromSystemProcess(); return bindServiceCommon(service, conn, flags, Process.myUserHandle()); }
可以看到最后是通过 ActivityManagerNative.getDefault().bindService() 来绑定服务
// bindServiceCommon() int res = ActivityManagerNative.getDefault().bindService( mMainThread.getApplicationThread(), getActivityToken(), service, service.resolveTypeIfNeeded(getContentResolver()), sd, flags, getOpPackageName(), user.getIdentifier()); // ActivityManagerNative.getDefault().bindService() public int bindService(IApplicationThread caller, IBinder token, Intent service, String resolvedType, IServiceConnection connection, int flags, String callingPackage, int userId) throws RemoteException { ... data.writeStrongBinder(connection.asBinder()); ... mRemote.transact(BIND_SERVICE_TRANSACTION, data, reply, 0); ... }
追踪到 ActivityManagerNative.getDefault().bindService() ,可以发现 ActivityManager
和 IServiceConnection 也是一个 AIDL
实现。通过它的 ActivityManagerProxy.bindService()
将绑定请求发送给本地层。
再从 onServiceConnected()
回调追踪, onServiceConnected() 是由 LoadedApk.ServiceDispatcher.doConnected() 回调的。
关于更多的 bindService()
远程服务创建及 ServiceConnection
回调, 请参考 Android 应用程序绑定服务(bindService)的过程源代码分析
利用进程间通信,我们可以实现简单的应用插件功能。关于 AIDL 在实际项目中的应用,可以参考 CallerInfo Plugin 的实现。
从上面分析可以看出, AIDL 的本质是对 Binder 的又一次抽象和封装,实际的进程间通信仍是由 Binder 完成的。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论