首先,来了解一下AIDL是什么?主要是干了一些什么事情?
AIDL是一种接口定义语言,主要的使用场景是在进程间的通信,通过它,我们在两个进程中依靠这套接口定义,去相互访问对方的数据。
这个AIDL在编写完成以后,通过make project就能在build/generated/source/aidl/debug目录下,生成一个接口文件,通过这个文件,我们可以调用里面的方法,实现两个进程的通信
我们切换一下视图结构: Structure
通过上面的视图,我们发现aidl文件有两个部分。
其中
Proxy -- 代理 相当于客户端。CS架构中的Client
Stub -- 存根 相当于服务器。CS架构中的Server
这两个在通信中的作用,下图画的非常清楚
具体实现:
在main目录下新建aidl文件夹
新建aidl文件,bean目录下的Person.aidl和IMyAidl.aidl文件
Person.aidl文件
// Person.aidl
package furobot.com.lsn6_aidl;
//声明一个实体类在一个包里
parcelable Person;
IMyAidl.aidl
// IMyAidl.aidl
package furobot.com.lsn6_aidl;
// Declare any non-default types here with import statements
interface IMyAidl {
//除了基本的数据类型,其他类型的参数都需要表上方向的类型,in 输入 ,out 输出 ,inout 输入输出
void addPerson(in Person person);//添加Person
List<Person> getPersonList();//获取Person列表
}
然后,进行make project
最后,会在build目录下,生成一个aidl接口文件
到了,这一步,我们开始编写通信的相关代码了,我们实现一个添加人(对象)和展示人(对象)的一个功能。我们在另外一个进程服务里面去处理对象的添加和展示,然后将处理后的结果返回给当前进程。
创建一个服务,并在主配置清单里面声明它在aidl进程里面
<service android:name=".MyAidlService"
android:enabled="true"
android:exported="true"
android:process=":aidl"/>
package furobot.com.lsn6_aidl;
import android.app.Person;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.annotation.Nullable;
import android.util.Log;
import java.util.ArrayList;
import java.util.List;
/**
* 服务实现接口,在onBind()中返回这个Binder,客户端就能拿到可以操作的数据了
*/
public class MyAidlService extends Service{
private static final String TAG = "MyAidlService";
private ArrayList<furobot.com.lsn6_aidl.bean.Person> mPersons;
public MyAidlService(){
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
mPersons = new ArrayList<>();
Log.e(TAG,"MyAidlService onBind");
return mBinder;
}
private IBinder mBinder = new IMyAidl.Stub() {
@Override
public void addPerson(furobot.com.lsn6_aidl.bean.Person person) throws RemoteException {
mPersons.add(person);
}
@Override
public List<furobot.com.lsn6_aidl.bean.Person> getPersonList() throws RemoteException {
return mPersons;
}
};
}
最后,在Activity里面进行调用
package furobot.com.lsn6_aidl;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import java.util.List;
import java.util.Random;
import furobot.com.lsn6_aidl.bean.Person;
public class MainActivity extends AppCompatActivity {
private IMyAidl myAidl;
private TextView mTv;
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//连接成功后,拿到Binder,转换成AIDL,在不同的进程中返回代理
myAidl = IMyAidl.Stub.asInterface(service); //将Ibinder转换成AIDL接口,这样才能调用里面的方法
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTv = findViewById(R.id.tv_text);
}
public void startService(View view){
bindService(new Intent(this,MyAidlService.class),mConnection,BIND_AUTO_CREATE);
}
public void addPerson(View view){
Random random = new Random();
Person person = new Person("shixin" + random.nextInt(10));
try {
myAidl.addPerson(person);
List<Person> personList = myAidl.getPersonList(); //调用远程的getPersonList()方法
mTv.setText(personList.toString());
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
效果图