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

含义: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
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值