看过官方文档以及其他的博客和慕课网对AIDL的介绍,做了以下的整理,方便随时查看:
AIDL介绍
AIDL(Android interface Definition Language,安卓接口定义语言),使用AIDL可以实现跨进程通信。
Android中的绑定服务有三种,分别是:扩展Binder类,Messenger,AIDL。
- 扩展Binder类主要用于服务只是本应用的后台工作线程。
- Messenger实现跨不同的进程工作,是执行进程间通信 (IPC) 的最简单方法,因为 Messenger 会在单一线程中创建包含所有请求的队列,服务一次接受一个请求,这样就不必对服务进行线程安全设计。
- AIDL用于跨进程通信,让服务同时处理多个请求,需要服务具备多线程处理能力,采用线程安全式设计。
注意:只有运行不同应用的客户端,用IPC访问服务,并且想要在服务中处理多线程时,才有必要使用AIDL。
AIDL创建
在Android Studio里,直接在Java包上右击,创建一个AIDL文件,就会自动生成aidl包,并创建了指定的aidl文件。
完成aidl文件的创建后,点击上方的
这样就会自动生成相应的java类:
AIDL实现
注意 AIDL中不能有修饰访问符(public,private,protected),支持Java基本数据类型(除short,例如int,long,char等),支持String,CharSequence,List,Map。必须为其他数据类型加入import语句。在方法参数使用时,所有非原语参数(我认为是其他数据类型),要有in,out,inout来标记数据走向,默认为in。(in表示客户端的参数输入,out表示服务端的参数输入,inout表示客户端可输入、服务端也可输入)
下面是使用AIDL进行简单的数据传输:
在IMyAIDL中声明一个方法,我们想要通过这个方法获取字符串信息,修改完毕后点击这个按钮,Android SDK工具会生成aidl文件相应的java接口文件
// IMyAIDL.aidl
package com.example.aidldemo;
interface IMyAIDL {
String getMessage(String s);
}
创建Service的类MyService,在Manifest中注册Service:
<service
android:name=".MyService"
android:enabled="true"
android:exported="true"></service>
我们通过SDK生成的java接口文件中包括一个名为Stub的子类,这个子类是其父接口的抽象实现,用于声明aidl文件中的所有方法。我们通过Service实现这个接口,向客户端公开接口,以便客户端进行绑定,这就需要通过onBinde方法了:
public class MyService extends Service {
public MyService() {
}
@Override
public IBinder onBind(Intent intent) {
return mbinder;
}
private final IMyAIDL.Stub mbinder = new IMyAIDL.Stub() {
@Override
public String getMessage(String s) throws RemoteException {
return "收到消息"+s;//返回获取到的内容
}
};
}
现在当客户端调用bindService连接服务器,客户端的OnServiceConnected()回调会接收服务的onBind()方法返回mbinder实例。Stub中定义了asInterface()方法,这个方法将IBinder传递给客户端的onServiceConnected()。
ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
iMyAIDL = IMyAIDL.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
iMyAIDL = null;
}
};
完整代码
public class MainActivity extends AppCompatActivity {
private TextView textView ;
private EditText editText;
private IMyAIDL iMyAIDL;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.text);
editText = (EditText) findViewById(R.id.edit);
Intent intent = new Intent(MainActivity.this, MyService.class);
bindService(intent, connection, Context.BIND_AUTO_CREATE);
}
ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
iMyAIDL = IMyAIDL.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
iMyAIDL = null;
}
};
public void startService(View view) {
try {
String message = iMyAIDL.getMessage(editText.getText().toString());
textView.setText(message);
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.aidldemo.MainActivity">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/edit"
/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="startService"
/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/text"
/>
</LinearLayout>
效果如图