一、概述
由于Android中两个进程间无法直接进行通信,但是有时候又会有这样的需求,所以在此,我们引入了AIDL(Android接口定义语言),目的是为了实现进程间通信,尤其是在涉及多进程并发情况下的进程间通信。这样我们就可以在一个进程访问另一个进程中的数据,甚至调用它的一些方法,当然,只能是特定的方法。
二、测试效果图
这里我们编写了一个测试案例实现在一个进程中调用另一个进程中的方法
三、核心代码
1.服务端
IMyAidl.aidl
// IMyAidl.aidl
package com.czhappy.aidldemo;
import com.czhappy.aidldemo.Person;
// Declare any non-default types here with import statements
interface IMyAidl {
int add(int num1, int num2);
List<Person> addPerson(in Person person);
}
Person.aidl
// IMyAidl.aidl
package com.czhappy.aidldemo;
parcelable Person;
IRemoteService.java
package com.czhappy.aidldemo;
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;
/**
* Description:
* User: chenzheng
* Date: 2017/1/6 0006
* Time: 11:41
*/
public class IRemoteService extends Service {
private List<Person> persons;
/**
* 当客户端绑定到该服务时调用
* @param intent
* @return
*/
@Nullable
@Override
public IBinder onBind(Intent intent) {
persons = new ArrayList<Person>();
return iBinder;
}
private IBinder iBinder = new IMyAidl.Stub(){
@Override
public int add(int num1, int num2) throws RemoteException {
Log.e("tag", "收到的两个参数为:"+num1+"和"+num2);
return num1+num2;
}
@Override
public List<Person> addPerson(Person person) throws RemoteException {
persons.add(person);
return persons;
}
};
}
Person.java
package com.czhappy.aidldemo;
import android.os.Parcel;
import android.os.Parcelable;
/**
* Description:
* User: chenzheng
* Date: 2017/1/6 0006
* Time: 15:00
*/
public class Person implements Parcelable{
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public Person(Parcel source) {
this.name = source.readString();
this.age = source.readInt();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeInt(age);
}
public static final Creator<Person> CREATOR = new Creator<Person>() {
@Override
public Person createFromParcel(Parcel source) {
return new Person(source);
}
@Override
public Person[] newArray(int size) {
return new Person[size];
}
};
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
2.客户端
其中IMyAidl.aidl和Person.aidl以及Person.java文件和服务端相同,特别注意的它们的包名都要完全一样,否则会报错。
MainActivity.java
package com.czhappy.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.EditText;
import com.czhappy.aidldemo.IMyAidl;
import com.czhappy.aidldemo.Person;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private EditText num1_et, num2_et, res_et;
private IMyAidl iMyAidl;
private ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//拿到了远程的服务
iMyAidl = IMyAidl.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
//回收
iMyAidl = null;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
bindService();
}
private void initView() {
num1_et = (EditText) findViewById(R.id.num1_et);
num2_et = (EditText) findViewById(R.id.num2_et);
res_et = (EditText) findViewById(R.id.res_et);
}
public void doAdd(View view){
int num1 = Integer.parseInt(num1_et.getText().toString());
int num2 = Integer.parseInt(num2_et.getText().toString());
try {
//调用远程的服务
int res = iMyAidl.add(num1, num2);
res_et.setText(res+"");
} catch (RemoteException e) {
e.printStackTrace();
}
}
public void getPersons(View view){
try {
List<Person> list = iMyAidl.addPerson(new Person("zhangsan", 21));
Log.e("tag", list.toString());
} catch (RemoteException e) {
e.printStackTrace();
}
}
/**
* 绑定服务
*/
private void bindService() {
Intent it = new Intent();
//5.0新版本必须显示Intent启动绑定服务
it.setComponent(new ComponentName("com.czhappy.aidldemo","com.czhappy.aidldemo.IRemoteService"));
bindService(it, conn, Context.BIND_AUTO_CREATE);
}
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(conn);
}
}
四、测试结果
点击计算按钮时后台打印:
多次点击获取集合按钮时后台打印:
五、注意事项
1.服务器端和客户端的aidl文件的包名和类名以及里面的内容都是完全一样的,否则会报java.lang.SecurityException: Binder invocation to an incorrect interface这种异常
2.先运行服务器端程序启动了服务,才能进行客户端demo的测试
3.服务器端记得添加service配置
<service android:name="com.czhappy.aidldemo.IRemoteService"
android:exported= "true"
android:process=":remote"/>
六、源码下载
http://download.csdn.net/detail/chenzheng8975/9730820