本文为Java实现,基本流程与参考链接一致,代码和可运行的APK文件在github文件夹中
service端实际架构如下(与android studio中的目录显示不太一样)
aidl是Android 接口定义语言,定义数据接口
通过android studio的build功能,可以自动生成IMyAidlInterface.aidl的java接口实现,位置在:
service端需要实现aidl中定义的RequestData类和ResponseData类,以及MyService类调用IMyAidlInterface.Stub对象的asBinder方法
parcelable定义了binder在用户空间使用的数据模型
package com.example.appbinder;
parcelable RequestData;
package com.example.appbinder;
parcelable ResponseData;
interface定义了一个binder service,在编译中aidl会自动生成两类binder对象:
interface中函数的参数
package com.example.appbinder;
import com.example.appbinder.RequestData;
import com.example.appbinder.ResponseData;
interface IMyAidlInterface {
ResponseData send(in RequestData request);
}
配置app的build.gradle
直接编译,在刚才的位置可以找到生成的IMyAidlInterface.java文件
实现Parcelable接口,有一个字符串作为私有变量,一个toString函数来打印RequestData类数据
package com.example.appbinder;
import android.os.Parcel;
import android.os.Parcelable;
import static android.os.UserHandle.readFromParcel;
public class RequestData implements Parcelable {
private String s;
protected RequestData(Parcel in) {
readFromParcel(in);
}
public RequestData(String s) {
this.s = s;
}
/** 将数据写入到Parcel **/
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(s);
}
/** 从Parcel中读取数据 **/
public void readFromParcel(Parcel in){
s = in.readString();
}
@Override
public int describeContents() {
return 0;
}
public static final Creator<RequestData> CREATOR = new Creator<RequestData>() {
@Override
public RequestData createFromParcel(Parcel in) {
return new RequestData(in);
}
@Override
public RequestData[] newArray(int size) {
return new RequestData[size];
}
};
@Override
public String toString() {
return s;
}
}
package com.example.appbinder;
import android.os.Parcel;
import android.os.Parcelable;
public class ResponseData implements Parcelable {
private String s;
protected ResponseData(Parcel in) {
readFromParcel(in);
}
public ResponseData(String s) {
this.s = s;
}
/** 将数据写入到Parcel **/
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(s);
}
/** 从Parcel中读取数据 **/
public void readFromParcel(Parcel in){
s = in.readString();
}
@Override
public int describeContents() {
return 0;
}
public static final Parcelable.Creator<ResponseData> CREATOR = new Parcelable.Creator<ResponseData>() {
@Override
public ResponseData createFromParcel(Parcel in) {
return new ResponseData(in);
}
@Override
public ResponseData[] newArray(int size) {
return new ResponseData[size];
}
};
@Override
public String toString() {
return s;
}
}
Service在onBind方法返回Binder实体,最后会注册到ServiceManager的映射表,供客户端调用;binder实体在IMyAidlInterface中已经被定义,只需要实现自定义的send方法
package com.example.appbinder;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
public class MyService extends Service {
private final IMyAidlInterface.Stub mBinder = new IMyAidlInterface.Stub() {
@Override
public ResponseData send(RequestData data) throws RemoteException {
Log.i("service","[RemoteService] receive "+ data.toString());
return new ResponseData("i'm service message");
}
};
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
}
启动service
package com.example.appbinder;
import androidx.appcompat.app.AppCompatActivity;
import android.content.ComponentName;
import android.content.Intent;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent in = new Intent();
in.setComponent(new ComponentName("com.example.appbinder", "com.example.appbinder.MyService"));
//启动service
startService(in);
}
}
注册service
<service
android:name=".MyService"
android:exported="true">
<intent-filter>
<action android:name="com.example.appbinder.service" />
<category android:name="android.intent.category.DEFAULT" />
intent-filter>
service>
aidl文件夹与server端一致,里面包含RequestData.aidl、ResponseData.aidl、IMyAidlInterface.aidl三个文件
java文件夹下com.example.appbinder文件夹中,包含RequestData.java、ResponseData.java两个文件
注意上面的文件与server端的完全相同,且包名也一致
同样需要配置app的build.gradle
同样对IMyAidlInterface.aidl进行编译得到IMyAidlInterface.java文件
实现bindservice,同时定义一个按钮,实现send发送消息和回显消息
package com.example.appbinderclient;
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.widget.TextView;
import com.example.appbinder.IMyAidlInterface;
import com.example.appbinder.RequestData;
import com.example.appbinder.ResponseData;
public class MainActivity extends AppCompatActivity {
private IMyAidlInterface mAidlInterface;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// bind上服务端的service
Intent in = new Intent();
in.setComponent(new ComponentName("com.example.appbinder", "com.example.appbinder.MyService"));
bindService(in, connD, Context.BIND_AUTO_CREATE);
}
private ServiceConnection connD = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mAidlInterface = IMyAidlInterface.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
mAidlInterface = null;
}
};
// 发送消息和回显消息
public void send(android.view.View v) {
try {
ResponseData data = mAidlInterface.send(new RequestData("hello i'm client"));
TextView textView = findViewById(R.id.textview);
textView.setText(data.toString());
} catch (Exception e) {
}
}
}
先打开server端:
然后打开客户端:
点击客户端的send按钮,客户端收到信息:
同时server端后台日志也说明收到了client端信息:
查看生成的IMyAidlInterface.java文件
IMyAidlInterface实现了android的IInterface接口:
Stub类继承了Binder类,为服务端
构造器Stub(),创建stub并附加到接口上
asInterface(Ibinder obj),提供给客户端调用
输入obj可以是Binder也可以是BinderProxy,客户端可以通过调用bindService bind to RemoteService,服务端自己也可以bind to RemoteService,两种情况下都会在onServiceConnected得到一个IBinder,但是如果是客户端IBinder类型为BinderProxy,如果是服务端类型为Binder。
public static com.example.appbinder.IMyAidlInterface asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
// DESCRIPTOR就是com.example.appbinder.IMyAidlInterface
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.example.appbinder.IMyAidlInterface))) {
return ((com.example.appbinder.IMyAidlInterface)iin);
}
return new com.example.appbinder.IMyAidlInterface.Stub.Proxy(obj);
}
onTransact是核心,Client调用aidl接口后,最终onTransact会接收到消息,并调用我们自己定义的方法
@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
{
java.lang.String descriptor = DESCRIPTOR;
switch (code)
{
case INTERFACE_TRANSACTION:
{
reply.writeString(descriptor);
return true;
}
case TRANSACTION_send:
{
data.enforceInterface(descriptor);
com.example.appbinder.RequestData _arg0;
if ((0!=data.readInt())) {
_arg0 = com.example.appbinder.RequestData.CREATOR.createFromParcel(data);
}
else {
_arg0 = null;
}
// 调用我们定义的方法
com.example.appbinder.ResponseData _result = this.send(_arg0);
reply.writeNoException();
if ((_result!=null)) {
reply.writeInt(1);
_result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
}
else {
reply.writeInt(0);
}
return true;
}
default:
{
return super.onTransact(code, data, reply, flags);
}
}
}
Proxy类为客户端
private static class Proxy implements com.example.appbinder.IMyAidlInterface
{
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote)
{
mRemote = remote;
}
@Override public android.os.IBinder asBinder()
{
return mRemote;
}
public java.lang.String getInterfaceDescriptor()
{
return DESCRIPTOR;
}
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
@Override public com.example.appbinder.ResponseData send(com.example.appbinder.RequestData request) throws android.os.RemoteException
{
// 序列化参数
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
com.example.appbinder.ResponseData _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
if ((request!=null)) {
_data.writeInt(1);
request.writeToParcel(_data, 0);
}
else {
_data.writeInt(0);
}
// 发送消息,调用Binder的onTransact方法
boolean _status = mRemote.transact(Stub.TRANSACTION_send, _data, _reply, 0);
if (!_status && getDefaultImpl() != null) {
return getDefaultImpl().send(request);
}
_reply.readException();
if ((0!=_reply.readInt())) {
//读取返回结果
_result = com.example.appbinder.ResponseData.CREATOR.createFromParcel(_reply);
}
else {
_result = null;
}
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
public static com.example.appbinder.IMyAidlInterface sDefaultImpl;
}
send方法是IMyAidlInterface中自己定义的函数
public com.example.appbinder.ResponseData send(com.example.appbinder.RequestData request) throws android.os.RemoteException;