Binder系列9—如何使用AIDL

Binder系列9—如何使用AIDL,第1张

概述copyfrom: http://gityuan.com/2015/11/23/binder-aidl/ 自定义binder架构的client/server组件一、AIDL1.1Server端RemoteService.java本例是为了演示进程间的通信机制,故需要将Service与Activity处于不同的进程,需要在AndroidManifest.xml中,把service配置成android:p

copy from: http://gityuan.com/2015/11/23/binder-aidl/

 

自定义binder架构的 clIEnt/ server组件

一、AIDL1.1 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所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1066053.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-26
下一篇 2022-05-26

发表评论

登录后才能评论

评论列表(0条)

保存