您的位置:首页 > 大数据 > 人工智能

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

2017-11-08 18:46 696 查看
含义: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;
}


源码点击下载
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐