android进程间通信,使用service,调用bindService来绑定服务,本例实现双向通信。
服务端
可以看到有三个aidl文件,是实现进程间通信必须的。
Iservice.aidl文件:服务要使用此文件产生的stub,调用方法的参数必须是基本数据类型,list,parcel(如EntityData)类型的
package com.hm.aidl;
import com.hm.aidl.ICallback;
import com.hm.aidl.EntityData;
interface IService
{
EntityData getCurrentData();
List<EntityData> getDatas();
void registerCallback(in ICallback callback);
}
ICallback.aidl文件:用于回调,服务端通知客户端
package com.hm.aidl;
import android.os.Bundle;
interface ICallback
{
void notify(String action, in Bundle bundle);
}
EntityData.java文件:EntityData必须是Parcelablel类型
package com.hm.aidl;
import android.os.Parcel;
import android.os.Parcelable;
public class EntityData implements Parcelable {
public int id;
public String name;
public EntityData() {
}
private EntityData(Parcel in) {
id = in.readInt();
name = in.readString();
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel out, int flags) {
out.writeInt(id);
out.writeString(name);
}
public static final Parcelable.Creator<EntityData> CREATOR = new Parcelable.Creator<EntityData>() {
public EntityData createFromParcel(Parcel in) {
return new EntityData(in);
}
public EntityData[] newArray(int size) {
return new EntityData[size];
}
};
}
另外也要创建一个EntityData.aidl文件,声明一下
package com.hm.aidl;
parcelable EntityData;
以上已经准备好通信的数据和接口,接下来就是创建服务MyService
首先在Manifest中注册
<service
android:name="com.example.server.MyService"
android:enabled="true"
android:exported="true" >
<intent-filter>
<action android:name="android.intent.action.HM_SERVICE" />
</intent-filter>
</service>
接下来看MyService.java文件
package com.example.server;
import java.util.ArrayList;
import java.util.List;
import com.hm.aidl.EntityData;
import com.hm.aidl.ICallback;
import com.hm.aidl.IService;
import android.app.Service;
import android.content.Intent;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
public class MyService extends Service {
private static final String TAG = "Whuthm Service";
@Override
public IBinder onBind(Intent intent) {
Log.i(TAG, "onBind");
return new IServiceImpl();
}
static class IServiceImpl extends IService.Stub {
ICallback mCallback;
List<EntityData> mDatas;
int mIndex = -1;
public IServiceImpl() {
mDatas = new ArrayList<EntityData>();
for (int i = 0; i < 5; i++) {
EntityData data = new EntityData();
data.id = i;
data.name = "EntityData " + i;
mDatas.add(data);
}
}
@Override
public EntityData getCurrentData() throws RemoteException {
Log.i(TAG, "getCurrentData");
int size = mDatas != null ? mDatas.size() : 0;
EntityData data = null;
if (mIndex >= 0 && mIndex < size) {
data = mDatas.get(mIndex);
}
if (size > 0) {
mIndex = (mIndex + 1) % size;
}
notityCallback("getCurrentData", null);
return data;
}
@Override
public List<EntityData> getDatas() throws RemoteException {
Log.i(TAG, "getDatas");
notityCallback("getDatas", null);
return mDatas;
}
@Override
public void registerCallback(ICallback callback) throws RemoteException {
Log.i(TAG, "registerCallback");
mCallback = callback;
notityCallback("registerCallback", null);
}
void notityCallback(String action, Bundle bundle) throws RemoteException {
if (mCallback != null) {
mCallback.notify(action, bundle);
}
}
}
}
可以看到服务关键在于onBind方法,此方法继承自一个IBinder,这里的IBinder即为上文提到的IService.aidl文件产生的stub。
IServiceImpl类实现IService.Stub,实现IService.aidl文件中所注明的方法,里面有一个registerCallback方法,参数为aidl文件产生的接口,此方法用于获取客户端的IBinder,然后用于服务端通知客户端,而其他方法则相反,客户端获取服务端的数据。