1.可以将多个客户端同时连接到某项服务。但是,系统会缓存 IBinder 服务通信通道。换言之,只有在第一个客户端绑定服务时,系统才会调用服务的 onBind() 方法来生成 IBinder。然后,系统会将该 IBinder 传递至绑定到同一服务的所有其他客户端,无需再次调用 onBind()。
2.当最后一个客户端取消与服务的绑定时,服务端会执行onUnbind,系统会销毁该服务.
注:纯AIDL 接口可能同时向服务发送多个请求,那么服务就必须执行多线程处理。
// AidlBean.aidl
package com.example.aidlservice;
// Declare any non-default types here with import statements
parcelable AidlBean;
// ICallback.aidl
package com.example.aidlservice;
import com.example.aidlservice.AidlBean;
// Declare any non-default types here with import statements
interface ICallback {//服务端反馈给客户端
void onResponseSuccess(String tag,String data,in AidlBean bean);
void onResponseErr(int type,String errMsg);
}
// IMyAidlInterface.aidl
package com.example.aidlservice;
import com.example.aidlservice.ICallback;
interface IMyAidlInterface {//提供客户端调用接口
/**
* input surface,surfaceWidth,surfaceHeight
*/
void setSurface(in Surface surface,in int width,in int height);
/**
* on client surface ondestroy
*/
void onSurfaceDestroy();
/**
* service use callback notify client
*/
void registerCallback(in ICallback callback,in String tag);
void unRegisterCallback(in ICallback callback,in String tag);
void getDataList(in String tag);
/**
* client use callback notify service
* it can work,but it has no value
*/
ICallback getCallback();
}
AndroidManifest.xml
package com.example.aidlservice;
import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;
import android.view.Surface;
import androidx.annotation.Nullable;
import com.example.aidlservice.util.L;
import org.json.JSONException;
import org.json.JSONObject;
/**
* @author Liushihua
* @date 2022-5-10 14:39
* @desc
*/
public class MyAidlService extends Service {
private ICallback callback;
private Handler handler = new Handler(Looper.myLooper());
private ICallback.Stub mCallback = new ICallback.Stub() {
@Override
public void onResponseSuccess(String tag, String data, AidlBean bean) throws RemoteException {
L.d("onResponseSuccess:" + data + " " + bean);
}
@Override
public void onResponseErr(int type, String errMsg) throws RemoteException {
}
};
private IMyAidlInterface.Stub binder = new IMyAidlInterface.Stub() {
@Override
public void setSurface(Surface surface, int width, int height) throws RemoteException {
L.d("setSurface width:" + width + " thread:" + Thread.currentThread().getId() + " binder:" + binder);
}
@Override
public void onSurfaceDestroy() throws RemoteException {
L.d("onSurfaceDestroy");
}
@Override
public void registerCallback(ICallback callback, String tag) throws RemoteException {
L.d("registerCallback:" + tag);
MyAidlService.this.callback = callback;
handler.postDelayed(new Runnable() {
@Override
public void run() {
try {
callback.onResponseSuccess(tag, "服务端延时反馈消息", new AidlBean("服务", "000", 0));
} catch (RemoteException e) {
e.printStackTrace();
}
}
}, 3000);
}
@Override
public void unRegisterCallback(ICallback callback, final String tag) throws RemoteException {
L.d("unRegisterCallback:" + tag);
MyAidlService.this.callback = null;
}
@Override
public void getDataList(final String tag) throws RemoteException {
try {
JSONObject object = new JSONObject();
for (int i = 1; i < 11; i++) {
object.put("key" + i, i);
}
callback.onResponseSuccess(tag, object.toString(), new AidlBean("服务getDataList", "000", 0));
} catch (JSONException e) {
e.printStackTrace();
}
}
@Override
public ICallback getCallback() throws RemoteException {
return mCallback;
}
};
@Nullable
@Override
public IBinder onBind(Intent intent) {
L.d("onBind:" + binder);
return binder;
}
@Override
public boolean onUnbind(Intent intent) {
L.d("onUnbind:" + Thread.currentThread().getId());
return super.onUnbind(intent);
}
@Override
public void onDestroy() {
L.d("onDestroy:" + Thread.currentThread().getId());
callback = null;
binder = null;
super.onDestroy();
}
}
package com.example.aidlservice;
import android.os.Parcel;
import android.os.Parcelable;
/**
* @author Liushihua
* @date 2022-5-11 13:44
* @desc
*/
public class AidlBean implements Parcelable {
private String name;
private int age;
private String id;
public AidlBean(Parcel in) {
name = in.readString();
age = in.readInt();
id = in.readString();
}
public AidlBean(String name,String id,int age){
this.name = name;
this.id = id;
this.age = age;
}
public static final Creator CREATOR = new Creator() {
@Override
public AidlBean createFromParcel(Parcel in) {
return new AidlBean(in);
}
@Override
public AidlBean[] newArray(int size) {
return new AidlBean[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeInt(age);
dest.writeString(id);
}
@Override
public String toString() {
return "AidlBean{" +
"name='" + name + '\'' +
", age=" + age +
", id='" + id + '\'' +
'}';
}
}
package com.example.aidlclient;
import androidx.appcompat.app.AppCompatActivity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import com.example.aidlservice.AidlBean;
import com.example.aidlservice.ICallback;
import com.example.aidlservice.IMyAidlInterface;
public class MainActivity extends AppCompatActivity {
private IMyAidlInterface anInterface;
private ICallback callService;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
L.d("connection onServiceConnected");
anInterface = IMyAidlInterface.Stub.asInterface(service);
try {
callService = anInterface.getCallback();
anInterface.setSurface(null, 333, 333);
callService.onResponseSuccess("来自客户端", "来自客户端", new AidlBean("客户端", "111", 1));
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
L.d("connection onServiceDisconnected");
}
};
private ICallback.Stub callback = new ICallback.Stub() {
@Override
public void onResponseSuccess(String tag, String data, AidlBean bean) throws RemoteException {
L.d("333 onResponseSuccess:" + data + " " + bean);
}
@Override
public void onResponseErr(int type, String errMsg) throws RemoteException {
L.d("333 onResponseErr:" + errMsg);
}
};
private void initView() {
findViewById(R.id.btn).setOnClickListener(v -> {
Intent intent = new Intent(IMyAidlInterface.class.getName());
intent.setPackage(IMyAidlInterface.class.getPackage().getName());
bindService(intent, connection, Context.BIND_AUTO_CREATE);
});
findViewById(R.id.btn_1).setOnClickListener(v -> {
try {
unbindService(connection);
} catch (Exception e) {
e.printStackTrace();
}
});
findViewById(R.id.btn_2).setOnClickListener(v -> {
try {
anInterface.registerCallback(callback, "333");
} catch (RemoteException e) {
e.printStackTrace();
}
});
findViewById(R.id.btn_3).setOnClickListener(v -> {
try {
anInterface.getDataList("TAG_333");
} catch (RemoteException e) {
e.printStackTrace();
}
});
}
}