AIDL实现不同应用之间跨进程通讯及传递与返回各种数据类型和远程接口回调

来源:互联网 发布:英语书籍阅读软件 编辑:程序博客网 时间:2024/05/04 23:00

含义:AIDL(Android Interface Definition Language),是android接口定义语言,这种语言定义了一个客户端和服务器通讯接口的一个标准、规范。

为什么要有AIDL?
 我们都知道android中的四大组件Activity,Broadcast,Content Provider,Service,前面我们应该都接触过除了Service的其他三个组件的进程间通讯的例子,比如:一个应用可以通过显示意图启动另外一个Activity,一个应用发送一个广播,然后被其他应用所接受,一个应用对外提供一个Content Provider,然后其他应用使用ContentResolver获取它提供的数据。这些都是进程间通讯的例子(通常情况下每个应用运行在一个独立的Linux进程中),那么Service这个组件也同样也可以实现垮进程通讯

本人工作项目做得是封闭式车载导航系统,各个应用进行数据交换是很常见的事,例如launcher是需要去拿蓝牙,收音或者多媒体等数据然后作相应操作,如果在这之间用广播作数据通讯显得太low并且也麻烦,所以一般都采用aidl这种方式进行数据交换,当然了 也可以在底层framework应用框架层写一个接口服务回调上层,这样上层每一个应用都可以进行监听获取数据,太多理论性的东西这里不去说,这边只做aidl的使用说明总结:

server端目录结构:
这里写图片描述

关键代码片段
服务端service类:

public class BTManagerService extends Service implements TimeCallBack {    private IBinder myBinder = new BTBinder();    private IBinder mClientBinder = null;    class BTDeathRecipient implements DeathRecipient {        @Override        public void binderDied() {            System.out.println("---binderDied()---   ");        }    }    private class BTBinder extends IBTService.Stub {        @Override        public void setPinCode(String pincode) throws RemoteException {            System.out.println("---setPinCode()---   " + pincode);        }        @Override        public void setClientBinder(IBinder client) throws RemoteException {            System.out.println("---setClientBinder()---   ");            mClientBinder = client;            mClientBinder.linkToDeath(new BTDeathRecipient(), 0);        }        @Override        public void setDeviceInfo(DeviceInfo deviceInfo) throws RemoteException {            System.out.println("---setDeviceInfo()---   " + deviceInfo.mDeviceName);        }        @Override        public void onRequestAudioFocus() throws RemoteException {            System.out.println("---onRequestAudioFocus()---   ");        }        @Override        public boolean isBTOpen() throws RemoteException {            return false;        }        @Override        public int getA2dpStatus() throws RemoteException {            return 0;        }        @Override        public String getLastTelephone() throws RemoteException {            return "asir";        }        @Override        public PlayStatusInfo getPlayStatusInfo() throws RemoteException {            PlayStatusInfo playStatusInfo = new PlayStatusInfo();            playStatusInfo.mMediaLength = 666;            return playStatusInfo;        }        @Override        public MediaID3Info getMediaID3Info() throws RemoteException {            MediaID3Info mediaID3Info = new MediaID3Info();            mediaID3Info.mMediaTitle = "asir";            return mediaID3Info;        }        @Override        public PhonebookInfo getCurrentRecordInfo() throws RemoteException {            PhonebookInfo phonebookInfo = new PhonebookInfo();            phonebookInfo.mTelephone = "563209751@qq.com";            return phonebookInfo;        }        @Override        public List<DeviceInfo> getDeviceInfoList() throws RemoteException {            List<DeviceInfo> list = new ArrayList<DeviceInfo>();            DeviceInfo d1 = new DeviceInfo();            d1.mDeviceStatus = 1;            DeviceInfo d2 = new DeviceInfo();            d2.mDeviceStatus = 2;            DeviceInfo d3 = new DeviceInfo();            d3.mDeviceStatus = 3;            list.add(d1);            list.add(d2);            list.add(d3);            return list;        }        @Override        public List<PhonebookInfo> getPhonebookList() throws RemoteException {            List<PhonebookInfo> list = new ArrayList<PhonebookInfo>();            PhonebookInfo f1 = new PhonebookInfo();            f1.mTelephone = "1";            PhonebookInfo f2 = new PhonebookInfo();            f2.mTelephone = "2";            PhonebookInfo f3 = new PhonebookInfo();            f3.mTelephone = "3";            list.add(f1);            list.add(f2);            list.add(f3);            return list;        }        @Override        public int onGetMicGainEvent(int[] configs) throws RemoteException {            for (int i : configs) {                System.out.println("-s-" + i);            }            return 0;        }        @Override        public int onSetMicGainEvent(String[] configs) throws RemoteException {            for (String str : configs) {                System.out.println("-s-" + str);            }            return 0;        }        @Override        public void registerCallback(IMediaPlayerListener listener) throws RemoteException {            System.out.println("---registerCallback()---");            if (null != listener && null == mListener) {                MainActivity.getMainActivity().setTimeCallBack(BTManagerService.this);                mListener = listener;                mRemoteCallbackList.register(mListener);            }        }        @Override        public void unregisterCallback(IMediaPlayerListener listener) throws RemoteException {            System.out.println("---unregisterCallback()---");            mRemoteCallbackList.unregister(mListener);            mListener = null;        }    }    private RemoteCallbackList<IMediaPlayerListener> mRemoteCallbackList = new RemoteCallbackList<IMediaPlayerListener>();    private IMediaPlayerListener mListener = null;    @Override    /**     * 媒体播放时间回调     */    public void timeChangeCallBack(String poi, String duration) {        try {            mListener.playTimeChangeListener(poi, duration);        } catch (Exception e) {            e.printStackTrace();        }    }    @Override    public void onCreate() {        super.onCreate();    }    @Override    public int onStartCommand(Intent intent, int flags, int startId) {        return super.onStartCommand(intent, flags, startId);    }    @Override    public IBinder onBind(Intent intent) {        return myBinder;    }    @Override    public boolean onUnbind(Intent intent) {        return super.onUnbind(intent);    }    @Override    public void onDestroy() {        super.onDestroy();    }}

aidl文件:
这里写图片描述

package com.asir.aidlserver;import java.util.List;import com.asir.aidlserver.DeviceInfo;import com.asir.aidlserver.PhonebookInfo;import com.asir.aidlserver.MediaID3Info;import com.asir.aidlserver.PlayStatusInfo;import com.asir.aidlserver.IMediaPlayerListener;interface IBTService {    void setPinCode(String pincode);    void setClientBinder(IBinder client);    void setDeviceInfo(in DeviceInfo deviceInfo);    void onRequestAudioFocus();    boolean isBTOpen();    int getA2dpStatus();    String getLastTelephone();    PlayStatusInfo getPlayStatusInfo();    MediaID3Info getMediaID3Info();    PhonebookInfo getCurrentRecordInfo();    List<DeviceInfo> getDeviceInfoList();    List<PhonebookInfo> getPhonebookList();    int onGetMicGainEvent(inout int[] configs);    int onSetMicGainEvent(inout String[] configs);    void registerCallback(IMediaPlayerListener listener);       void unregisterCallback(IMediaPlayerListener listener);}

注意事项:
1、客户端使用时必须要完整拷贝服务端的包及包下的相关AIDL文件和aidl文件中引用到的相关对象接口等java文件
2、对于aidl文件中用到的对象必须要进行序列化
如代码:

public class PhonebookInfo implements Parcelable {    public int mType;    public String mTelephone = null;    public String mUserName = null;    public PhonebookInfo() {        mType = 0;        mTelephone = new String();        mUserName = new String();    }    private PhonebookInfo(Parcel source) {        mType = source.readInt();        mTelephone = source.readString();        mUserName = source.readString();    }    @Override    public int describeContents() {        // TODO Auto-generated method stub        return 0;    }    @Override    public void writeToParcel(Parcel dest, int flags) {        dest.writeInt(mType);        dest.writeString(mTelephone);        dest.writeString(mUserName);    }    public static final Parcelable.Creator<PhonebookInfo> CREATOR = new Parcelable.Creator<PhonebookInfo>() {        @Override        public PhonebookInfo createFromParcel(Parcel source) {            return new PhonebookInfo(source);        }        @Override        public PhonebookInfo[] newArray(int size) {            return new PhonebookInfo[size];        }    };}

3、传递数组、对象等要用关键字(in,inout)
4、客户端远程接口回调用完一定要释放(unregister)掉,确保clinet端和server端的远程回调接口是一样的,否则会造成内存泄露拿不到数据

客户端目录结构:
这里写图片描述

关键代码片段:

private final class BTConnection implements ServiceConnection {        @Override        public void onServiceConnected(ComponentName name, IBinder service) {            mBTService = IBTService.Stub.asInterface(service);            try {                if (null == mIM) {                    mIM = new IMediaPlayerListener.Stub() {                        @Override                        public void playTimeChangeListener(String poi, String duration) throws RemoteException {                            System.out.println(poi + " --- " + duration);                        }                    };                    mBTService.registerCallback(mIM);                }            } catch (RemoteException e) {                e.printStackTrace();            }        }        @Override        public void onServiceDisconnected(ComponentName name) {            mBTService = null;        }    }    private void onBindService() {        if (mBTService == null && mBTConnection != null) {            Intent intent = new Intent("com.asir.aidlserver.BTManagerService");            MainActivity.this.bindService(intent, mBTConnection, BIND_AUTO_CREATE);        }    }    private void onUnbindService() {        if (mBTService != null && mBTConnection != null) {            MainActivity.this.unbindService(mBTConnection);            try {                mBTService.unregisterCallback(mIM); // 此处一定要进行资源释放,否则重新加载时会造成内存泄露            } catch (RemoteException e) {                e.printStackTrace();            }        }        mBTService = null;        mBTConnection = null;    }

源码点击下载

阅读全文
0 0
原创粉丝点击