copy from: http://gityuan.com/2015/11/23/binder-aidl/
一、AIDL1.1 Server端自定义binder架构的 clIEnt/ server组件
RemoteService.java
本例是为了演示进程间的通信机制,故需要将Service与Activity处于不同的进程,需要在AndroIDManifest.xml中,把service配置成androID:process=":remote"
,进程也可以命名成其他的。
public class RemoteService extends Service { private static final String TAG = "BinderSimple"; MyData mMyData; @OverrIDe public voID onCreate() { super.onCreate(); Log.i(TAG, "[RemoteService] onCreate"); initMyData(); } @OverrIDe public IBinder onBind(Intent intent) { Log.i(TAG,"[RemoteService] onBind"); return mBinder; } @OverrIDe public boolean onUnbind(Intent intent) { Log.i(TAG, "[RemoteService] onUnbind"); return super.onUnbind(intent); } @OverrIDe public voID onDestroy() { Log.i(TAG, "[RemoteService] onDestroy"); super.onDestroy(); } /** * 实现IRemoteService.aIDl中定义的方法 */ private final IRemoteService.Stub mBinder = new IRemoteService.Stub() { @OverrIDe public int getPID() throws remoteexception { Log.i(TAG,"[RemoteService] getPID()="+androID.os.Process.myPID()); return androID.os.Process.myPID(); } @OverrIDe public MyData getMyData() throws remoteexception { Log.i(TAG,"[RemoteService] getMyData() "+ mMyData.toString()); return mMyData; } /**此处可用于权限拦截**/ @OverrIDe public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws remoteexception { return super.onTransact(code, data, reply, flags); } }; /** * 初始化MyData数据 **/ private voID initMyData() { mMyData = new MyData(); mMyData.setData1(10); mMyData.setData2(20); }}
1.2 ClIEnt端ClIEntActivity.java
public class ClIEntActivity extends AppCompatActivity { private static final String TAG = "BinderSimple"; private IRemoteService mRemoteService; private boolean mIsBound; private TextVIEw mCallBackTv; @OverrIDe protected voID onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.i(TAG, "[ClIEntActivity] onCreate"); setContentVIEw(R.layout.activity_main); mCallBackTv = (TextVIEw) findVIEwByID(R.ID.tv_callback); mCallBackTv.setText(R.string.remote_service_unattached); } /** * 用语监控远程服务连接的状态 */ private ServiceConnection mConnection = new ServiceConnection() { @OverrIDe public voID onServiceConnected(Componentname name, IBinder service) { mRemoteService = IRemoteService.Stub.asInterface(service); String pIDInfo = null; try { MyData myData = mRemoteService.getMyData(); pIDInfo = "pID="+ mRemoteService.getPID() + ", data1 = "+ myData.getData1() + ", data2="+ myData.getData2(); } catch (remoteexception e) { e.printstacktrace(); } Log.i(TAG, "[ClIEntActivity] onServiceConnected "+pIDInfo); mCallBackTv.setText(pIDInfo); Toast.makeText(ClIEntActivity.this, R.string.remote_service_connected, Toast.LENGTH_SHORT).show(); } @OverrIDe public voID onServicedisconnected(Componentname name) { Log.i(TAG, "[ClIEntActivity] onServicedisconnected"); mCallBackTv.setText(R.string.remote_service_disconnected); mRemoteService = null; Toast.makeText(ClIEntActivity.this, R.string.remote_service_disconnected, Toast.LENGTH_SHORT).show(); } }; public voID clickHandler(VIEw vIEw){ switch (vIEw.getID()){ case R.ID.btn_bind: bindRemoteService(); break; case R.ID.btn_unbind: unbindRemoteService(); break; case R.ID.btn_kill: killRemoteService(); break; } } /** * 绑定远程服务 */ private voID bindRemoteService(){ Log.i(TAG, "[ClIEntActivity] bindRemoteService"); Intent intent = new Intent(ClIEntActivity.this, RemoteService.class); intent.setAction(IRemoteService.class.getname()); bindService(intent, mConnection, Context.BIND_auto_CREATE); mIsBound = true; mCallBackTv.setText(R.string.binding); } /** * 解除绑定远程服务 */ private voID unbindRemoteService(){ if(!mIsBound){ return; } Log.i(TAG, "[ClIEntActivity] unbindRemoteService ==>"); unbindService(mConnection); mIsBound = false; mCallBackTv.setText(R.string.unbinding); } /** * 杀死远程服务 */ private voID killRemoteService(){ Log.i(TAG, "[ClIEntActivity] killRemoteService"); try { androID.os.Process.killProcess(mRemoteService.getPID()); mCallBackTv.setText(R.string.kill_success); } catch (remoteexception e) { e.printstacktrace(); Toast.makeText(ClIEntActivity.this, R.string.kill_failure, Toast.LENGTH_SHORT).show(); } }}
1.3 AIDL文件(1)IRemoteService.aIDl 定义远程通信的接口方法
interface IRemoteService { int getPID(); MyData getMyData();}
(2)MyData.aIDl 定义远程通信的自定义数据
parcelable MyData;
1.4 Parcel数据MyData.java
public class MyData implements Parcelable { private int data1; private int data2; public MyData(){ } protected MyData(Parcel in) { readFromParcel(in); } public static final Creator<MyData> CREATOR = new Creator<MyData>() { @OverrIDe public MyData createFromParcel(Parcel in) { return new MyData(in); } @OverrIDe public MyData[] newArray(int size) { return new MyData[size]; } }; @OverrIDe public int describeContents() { return 0; } /** 将数据写入到Parcel **/ @OverrIDe public voID writetoParcel(Parcel dest, int flags) { dest.writeInt(data1); dest.writeInt(data2); } /** 从Parcel中读取数据 **/ public voID readFromParcel(Parcel in){ data1 = in.readInt(); data2 = in.readInt(); } public int getData2() { return data2; } public voID setData2(int data2) { this.data2 = data2; } public int getData1() { return data1; } public voID setData1(int data1) { this.data1 = data1; } @OverrIDe public String toString() { return "data1 = "+ data1 + ", data2="+ data2; }}
1.5 运行该工程会生成一个apk,安装到手机,打开apk,界面如下:
界面上有三个按钮,分别是功能分别是bindService(绑定Service), unbindService(解除绑定Service), killProcess(杀死Service进程)。
从左往右,依次点击界面,可得:
二、原理分析调用图:
2.1 源码采用AIDL技术,是原理还是利用framework binder的架构。本文的实例AIDL会自动生成一个与之相对应的IRemoteService.java文件,如下:
package com.gityuan.appbinderdemo;public interface IRemoteService extends androID.os.IInterface { public static abstract class Stub extends androID.os.Binder implements com.gityuan.appbinderdemo.IRemoteService { private static final java.lang.String DESCRIPTOR = "com.gityuan.appbinderdemo.IRemoteService"; /** * Stub构造函数 */ public Stub() { this.attachInterface(this, DESCRIPTOR); } /** * 将IBinder 转换为IRemoteService interface */ public static com.gityuan.appbinderdemo.IRemoteService asInterface(androID.os.IBinder obj) { if ((obj == null)) { return null; } androID.os.IInterface iin = obj.queryLocalinterface(DESCRIPTOR); if (((iin != null) && (iin instanceof com.gityuan.appbinderdemo.IRemoteService))) { return ((com.gityuan.appbinderdemo.IRemoteService) iin); } return new com.gityuan.appbinderdemo.IRemoteService.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_getPID: { data.enforceInterface(DESCRIPTOR); int _result = this.getPID(); reply.writeNoException(); reply.writeInt(_result); return true; } case TRANSACTION_getMyData: { data.enforceInterface(DESCRIPTOR); com.gityuan.appbinderdemo.MyData _result = this.getMyData(); reply.writeNoException(); if ((_result != null)) { reply.writeInt(1); _result.writetoParcel(reply, androID.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE); } else { reply.writeInt(0); } return true; } } return super.onTransact(code, data, reply, flags); } private static class Proxy implements com.gityuan.appbinderdemo.IRemoteService { private androID.os.IBinder mRemote; /** * Proxy构造函数 */ Proxy(androID.os.IBinder remote) { mRemote = remote; } @OverrIDe public androID.os.IBinder asBinder() { return mRemote; } public java.lang.String getInterfaceDescriptor() { return DESCRIPTOR; } @OverrIDe 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; } @OverrIDe public com.gityuan.appbinderdemo.MyData getMyData() throws androID.os.remoteexception { androID.os.Parcel _data = androID.os.Parcel.obtain(); androID.os.Parcel _reply = androID.os.Parcel.obtain(); com.gityuan.appbinderdemo.MyData _result; try { _data.writeInterfacetoken(DESCRIPTOR); mRemote.transact(Stub.TRANSACTION_getMyData, _data, _reply, 0); _reply.readException(); if ((0 != _reply.readInt())) { _result = com.gityuan.appbinderdemo.MyData.CREATOR.createFromParcel(_reply); } else { _result = null; } } finally { _reply.recycle(); _data.recycle(); } return _result; } } static final int TRANSACTION_getPID = (androID.os.IBinder.FirsT_CALL_TRANSACTION + 0); static final int TRANSACTION_getMyData = (androID.os.IBinder.FirsT_CALL_TRANSACTION + 1); } public int getPID() throws androID.os.remoteexception; public com.gityuan.appbinderdemo.MyData getMyData() throws androID.os.remoteexception;}
总结 以上是内存溢出为你收集整理的Binder系列9—如何使用AIDL全部内容,希望文章能够帮你解决Binder系列9—如何使用AIDL所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)