AIDL(Android Interface Definition Language)是Android中为实现IPC(Inter Process Communication,进程间通信)的一种方式,本质是通过Binder实现,Binder是Android中最具特色的、广泛应用的进程间通信框架,具有高性能、高稳定性、安全性强、面向对象简单易用等优点。我们在定义好AIDL文件后,与wsdl类似的ide会帮我们自动生成了Binder类的相关代码,本文记录一个WSDL的简单使用,通过AIDL实现计算两数之和的事例。
1. 实现远程服务(Service)
两个进程通信,即需要一个提供服务的service,和一个调用服务的client。
1.1 创建AIDL File
首先创建一个项目作为service,直接new一个AIDL File,添加一个计算两数之和的方法
interface IMyAidlInterface {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
double aDouble, String aString);
int add(int v1, int v2);
}
然后sync一下项目使之生成IMyAidlInterface.java这个文件。
1.2 创建Service
创建一个Service实现远程服务,其中onBind方法会返回一个IBinder类的对象,这个IBinder类的对象就是远程服务的具体业务实现。为了实现这个服务,我们要用到自动生成的子类IMyAidlInterface.Stub,在此来实现我们之前在AIDL文件中定义的add()方法。
package com.example.aidl;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
public class MyService extends Service {
public MyService() {
}
@Override
public IBinder onBind(Intent intent) {
return new MyBinder();
}
class MyBinder extends IMyAidlInterface.Stub {
@Override
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
}
@Override
public int add(int v1, int v2) throws RemoteException {
return v1 + v2;
}
}
}
在AndroidManifest.xml中为service添加过滤
<service
android:name=".MyService"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.example.aidl.MyService"/>
</intent-filter>
</service>
至此,service已完成
2. 实现Client调用服务
创建新项目作为client。
2.1 创建AIDL File
将刚刚service端创建的AIDL文件从aidl层拷贝到main文件夹下,或重新new一个一模一样的,注意包名不可改变
sync一下项目生成IMyAidlInterface.java文件
2.2 调用服务
2.2.1 创建ServiceConnection内部类
为了调用service提供的服务,client需要实现ServiceConnection类来创建服务连接对象,在client端Activity创建一个内部类AdditionServiceConnection,这个类继承ServiceConnection类,并且重写了它的两个方法:onServiceConnected和onServiceDisconnected分别为绑定成功和解绑时的回调方法。该方法接收在service端定义的MyService的实现作为参数,随后被转换为client端自己的AIDL的实现,通过IMyAidlInterface.Stub.asInterface((IBinder) boundService)来获取iMyAidlInterface实例。
class AdditionServiceConnection implements ServiceConnection {
public void onServiceConnected(ComponentName name, IBinder boundService) {
iMyAidlInterface = IMyAidlInterface.Stub.asInterface((IBinder) boundService);
Toast.makeText(MainActivity.this, "Service connected", Toast.LENGTH_LONG).show();
}
public void onServiceDisconnected(ComponentName name) {
iMyAidlInterface = null;
Toast.makeText(MainActivity.this, "Service disconnected", Toast.LENGTH_LONG).show();
}
}
2.2.2 绑定服务
通过对Intent设置service端的Action和Package参数来绑定服务:
connection = new AdditionServiceConnection();
Intent i = new Intent();
i.setPackage("com.example.aidl");
i.setAction("com.example.aidl.MyService");
bindService(i, connection, Context.BIND_AUTO_CREATE);
输入两个整数求和,在模拟器上测试,启动两个app连接成功:
以下为client端页面布局和Activity的完整代码:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center_horizontal"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Add by AIDL"
android:textSize="21sp"
android:layout_marginTop="30dp"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<EditText
android:id="@+id/v1"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:gravity="center_horizontal">
</EditText>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="+"
android:textSize="36sp" />
<EditText
android:id="@+id/v2"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:gravity="center_horizontal">
</EditText>
<Button
android:id="@+id/bt_sum"
android:layout_width="50dp"
android:layout_height="wrap_content"
android:hint="=" >
</Button>
<TextView
android:id="@+id/result"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/result"
android:textSize="21sp" />
</LinearLayout>
</LinearLayout>
package com.example.aidl2;
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 android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import com.example.aidl.IMyAidlInterface;
public class MainActivity extends AppCompatActivity {
private IMyAidlInterface iMyAidlInterface;
AdditionServiceConnection connection;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btSum = findViewById(R.id.bt_sum);
btSum.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
TextView result = findViewById(R.id.result);
EditText value1 = findViewById(R.id.v1);
EditText value2 = findViewById(R.id.v2);
int v1, v2, res = 0;
v1 = Integer.parseInt(value1.getText().toString());
v2 = Integer.parseInt(value2.getText().toString());
try {
res = iMyAidlInterface.add(v1, v2);
} catch (RemoteException e) {
e.printStackTrace();
}
result.setText(res + "");
}
});
connection = new AdditionServiceConnection();
Intent i = new Intent();
i.setPackage("com.example.aidl");
i.setAction("com.example.aidl.MyService");
bindService(i, connection, Context.BIND_AUTO_CREATE);
}
class AdditionServiceConnection implements ServiceConnection {
public void onServiceConnected(ComponentName name, IBinder boundService) {
iMyAidlInterface = IMyAidlInterface.Stub.asInterface((IBinder) boundService);
Toast.makeText(MainActivity.this, "Service connected", Toast.LENGTH_LONG).show();
}
public void onServiceDisconnected(ComponentName name) {
iMyAidlInterface = null;
Toast.makeText(MainActivity.this, "Service disconnected", Toast.LENGTH_LONG).show();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(connection);
connection = null;
}
}