AIDL(Android Interface Definition Language,即Android接口定义语言。)
IPC(Inter-Process Communication,进程间通信)。
在进程间通信不一定需要AIDL,因为两个进程间不能直接通信,需要Android系统底层间接实现通信,所以比较耗资源,能不用就不用。如下图:
进程间通讯可以分为下面几种:
AIDL
在IPC时,并且多个应用,多线程时才用到。
Binder
只有IPC,多个应用,没有多线程
Messager
只有IPC,没有多线程
官方文档上的例子:
// IRemoteService.aidl,//包名,文件必须放在指定的目录
package com.example.android;
// Declare any non-default types here with import statements
/** Example service interface */
interface IRemoteService {
/** Request the process ID of this service, to do evil things with it. */
int getPid();
/** 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);
}
官方文档上写AIDL支持的数据类型包括:
那AIDL文件我们怎么转成java文件呢?在sdk\build-tools\23.0.2(版本)下有个aidl.exe文件,我们就是用这个来转成java文件:
输入命令:aidl IRemoteService.aidl
就会生成一个同名的java文件。
新建一个Android项目后,直接在java文件中new一个aidl文件
在eclipse中自动编译生成java,而java就和R文件在一起:
这样就可以直接在Activity中提示出来了
而Android studio中和eclipse有点不同,是和java同级目录创建
编译后生成的java文件:
客户端传两个数字,调用服务端的计算方法求和
首先服务端的AIDL文件代码:
package com.hou.aidl;
interface IMyAidlInterface {
int add(int num1,int num2);
}
package com.hou.aidl;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
public class IRemoteService extends Service {
//当客户端绑定服务时,会返回iBinder对象
@Override
public IBinder onBind(Intent intent) {
return iBinder;
}
private IBinder iBinder = new IMyAidlInterface.Stub() {
@Override
public int add(int num1, int num2) throws RemoteException {
Log.e("111", "收到了远程传过来的值" + num1 + "和" + num2);
return num1 + num2;
}
};
}
<service android:name=".IRemoteService">
<intent-filter>
<action android:name="com.hou.aidl.client" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</service>
package com.hou.aidlclient;
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.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import com.hou.aidl.IMyAidlInterface;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private EditText et_num1;
private EditText et_num2;
private EditText et_sum;
private Button btn_sum;
private IMyAidlInterface iMyAidlInterface;
private ServiceConnection conn = new ServiceConnection() {
//服务绑定上的时候
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.e("111", "绑定服务成功==" + name);
iMyAidlInterface = IMyAidlInterface.Stub.asInterface(service);
}
//服务断开的时候
@Override
public void onServiceDisconnected(ComponentName name) {
Log.e("111", "服务断开连接==" + name);
iMyAidlInterface = null;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
bindAidlService();
}
private void initView() {
et_num1 = (EditText) findViewById(R.id.et_num1);
et_num2 = (EditText) findViewById(R.id.et_num2);
et_sum = (EditText) findViewById(R.id.et_sum);
btn_sum = (Button) findViewById(R.id.btn_sum);
btn_sum.setOnClickListener(this);
}
@Override
public void onClick(View v) {
int num1 = Integer.parseInt(et_num1.getText().toString());
int num2 = Integer.parseInt(et_num2.getText().toString());
try {
int sum = iMyAidlInterface.add(num1, num2);
et_sum.setText(sum + "");
} catch (RemoteException e) {
et_sum.setText("出错了");
e.printStackTrace();
}
}
//绑定服务
private void bindAidlService() {
Intent intent = new Intent();
//在Android5.0以后只能已显示intent方式启动 绑定服务
intent.setComponent(new ComponentName("com.hou.aidl", "com.hou.aidl.IRemoteService"));
// Intent intent = new Intent("com.hou.aidl.client");//隐式意图方式
bindService(intent, conn, Context.BIND_AUTO_CREATE);//Context.BIND_AUTO_CREATE自动创建
}
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(conn);
}
}
现在就可以使用了,启动服务端,打开客户端就可以求和计算。
当然除过上边提到的类型外,我们经常会传递自定义类型的数据,比如一个对象Person。
创建一个Person对象,实现Parcelable序列化:
package com.hou.aidl;
import android.os.Parcel;
import android.os.Parcelable;
/** * Created by hp on 2016/3/9. */
public class Person implements Parcelable {
public String name;
public int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
protected Person(Parcel in) {
//必须和writeToParcel中写入的顺序一致;
name = in.readString();
age = in.readInt();
}
public static final Creator<Person> CREATOR = new Creator<Person>() {
@Override
public Person createFromParcel(Parcel in) {
return new Person(in);
}
@Override
public Person[] newArray(int size) {
return new Person[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeInt(age);
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
创建Person.aidl
package com.hou.aidl;
parcelable Person;
package com.hou.aidl;
//需要引入Person
import com.hou.aidl.Person;
interface IMyAidlInterface {
List<Person> add(in Person person);
}
Service:
package com.hou.aidl;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import java.util.ArrayList;
import java.util.List;
public class IRemoteService extends Service {
List<Person> persons;
//当客户端绑定服务时,会返回iBinder对象
@Override
public IBinder onBind(Intent intent) {
persons = new ArrayList<>();
return iBinder;
}
private IBinder iBinder = new IMyAidlInterface.Stub() {
@Override
public List<Person> add(Person person) throws RemoteException {
persons.add(person);
return persons;
}
};
}
把IMyAidlInterface.aidl和Person.aidl都复制到客户端同名包下(aidl-com.hou.aidl)
把Person复制到客户端同名包下(com.hou.aidl)
package com.hou.aidlclient;
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.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import com.hou.aidl.IMyAidlInterface;
import com.hou.aidl.Person;
import java.util.List;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Button btn_sum;
private IMyAidlInterface iMyAidlInterface;
private ServiceConnection conn = new ServiceConnection() {
//服务绑定上的时候
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.e("111", "绑定服务成功==" + name);
iMyAidlInterface = IMyAidlInterface.Stub.asInterface(service);
}
//服务断开的时候
@Override
public void onServiceDisconnected(ComponentName name) {
Log.e("111", "服务断开连接==" + name);
iMyAidlInterface = null;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
bindAidlService();
}
private void initView() {
btn_sum = (Button) findViewById(R.id.btn_sum);
btn_sum.setOnClickListener(this);
}
@Override
public void onClick(View v) {
try {
List<Person> persons = iMyAidlInterface.add(new Person("李四", 18));
Person person = persons.get(0);
et_sum.setText(person.toString());
} catch (RemoteException e) {
et_sum.setText("出错了");
e.printStackTrace();
}
}
//绑定服务
private void bindAidlService() {
Intent intent = new Intent();
//在Android5.0以后只能已显示intent方式启动 绑定服务
intent.setComponent(new ComponentName("com.hou.aidl", "com.hou.aidl.IRemoteService"));
// Intent intent = new Intent("com.hou.aidl.client");//隐式意图方式
bindService(intent, conn, Context.BIND_AUTO_CREATE);//Context.BIND_AUTO_CREATE自动创建
}
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(conn);
}
}