本篇主要介绍Android中通过AIDL进行进程间通信。
服务端
首先,我们来新建一个Android项目,这个项目是提供服务的,
第一步,定义一个需要传输对象的实体类,这个类需要实现序列化:
例如,我们定义一个Student 类
package com.aidl;
import android.os.Parcel;
import android.os.Parcelable;
public class Student implements Parcelable {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
protected Student(Parcel in) {
name = in.readString();
age = in.readInt();
}
public static final Creator<Student> CREATOR = new Creator<Student>() {
@Override
public Student createFromParcel(Parcel in) {
return new Student(in);
}
@Override
public Student[] newArray(int size) {
return new Student[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeInt(age);
}
}
然后,新建Student的AIDL声明,
选中app,File->New->AIDL->AIDLFile
完成后目录结构为:
打开刚才新建的Student.aidl文件,修改为
// Student.aidl
package com.aidl;
parcelable Student;
注意:parcelable 为小写。
下一步,新建一个StudentManager.aidl:
选中aidl文件夹,点击鼠标右键,选择 New->AIDL->AIDLFile
声明对外开放的接口,导入需要传输的对象完整路径:
package com.aidl;
import com.aidl.Student;
interface StudentManager {
//所有的返回值前都不需要加任何东西,不管是什么数据类型
List<Student> getStudents();
//传参时除了Java基本类型以及String,CharSequence之外的类型
//都需要在前面加上定向tag,具体加什么量需而定
void addStudent(in Student s);
}
现在,点击菜单栏 Build->Rebuild Project
下面,新建一个Service对外提供服务:
package com.aidl;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
public class StudentService extends Service {
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
实现我们声明的方法,并绑定服务时,返回StudentManager.Stub对象,
完整代码如下:
package com.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 StudentService extends Service {
List<Student> students = new ArrayList<>();
private StudentManager.Stub stub = new StudentManager.Stub() {
@Override
public List<Student> getStudents() throws RemoteException {
synchronized (this){
return students;
}
}
@Override
public void addStudent(Student s) throws RemoteException {
synchronized (this) {
if (s == null) {
throw new RemoteException("学生为空");
} else if (students.contains(s)) {
throw new RemoteException("学生已存在");
} else {
students.add(s);
}
}
}
};
@Override
public IBinder onBind(Intent intent) {
return stub;
}
}
最后一步,在AndroidManifest.xml文件中注册我们的服务,不要忘了添加action:
<service android:name=".StudentService">
<intent-filter>
<action android:name="STUDENT_SERVICE" />
</intent-filter>
</service>
OK,到此服务端结束。
客户端
首先新建一个AndroidProject
新建aidl文件夹:
File->New->Folder->AIDLFolder
在aidl文件夹新建服务端同名的包,将两个aidl文件复制过来
将Student类复制过来,并放入和服务端相同的包下
点击菜单栏 Build->Rebuild Project
编写页面布局
<?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"
tools:context="com.aidl.client.MainActivity">
<ScrollView
android:id="@+id/scrollView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<TextView
android:id="@+id/log"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</ScrollView>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/add"
android:text="add"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_margin="20dp"/>
<Button
android:id="@+id/get"
android:text="get"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_margin="20dp"/>
</LinearLayout>
</LinearLayout>
写MainActivity的逻辑,直接上代码
package com.aidl.client;
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.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;
import com.aidl.Student;
import com.aidl.StudentManager;
import java.util.List;
import java.util.Random;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private ScrollView scrollView;
private TextView tvLog;
private Button btAdd;
private Button btGet;
private StringBuffer log = new StringBuffer();
//由AIDL文件生成的Java类
private StudentManager manager = null;
//标志当前与服务端连接状况的布尔值,false为未连接,true为连接中
private boolean mBound = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
private void initView() {
scrollView = (ScrollView) findViewById(R.id.scrollView);
tvLog = (TextView) findViewById(R.id.log);
btAdd = (Button) findViewById(R.id.add);
btGet = (Button) findViewById(R.id.get);
btAdd.setOnClickListener(this);
btGet.setOnClickListener(this);
}
@Override
protected void onStart() {
super.onStart();
if (!mBound) {
attemptToBindService();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mBound) {
unbindService(mServiceConnection);
mBound = false;
}
}
/**
* 检查连接状态
*
* @return
*/
private boolean checkConnect() {
if (!mBound) {
attemptToBindService();
Toast.makeText(this, "正在尝试重连,请稍后再试", Toast.LENGTH_SHORT).show();
setLog("正在尝试重连,请稍后再试");
return true;
}
if (manager != null) return true;
return false;
}
/**
* 尝试与服务端建立连接
*/
private void attemptToBindService() {
Intent intent = new Intent();
intent.setAction("STUDENT_SERVICE");
intent.setPackage("com.aidl");
bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
}
private ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
setLog("service connected");
manager = StudentManager.Stub.asInterface(service);
mBound = true;
}
@Override
public void onServiceDisconnected(ComponentName name) {
setLog("service disconnected");
mBound = false;
}
};
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.add:
addStudent();
break;
case R.id.get:
getStudents();
break;
default:
break;
}
}
Random random = new Random();
private void addStudent() {
if (!checkConnect()) return;
try {
Student s = new Student("s" + random.nextInt(1000), random.nextInt(20));
manager.addStudent(s);
setLog("add student success");
} catch (Exception e) {
e.printStackTrace();
}
}
private void getStudents() {
if (!checkConnect()) return;
try {
List<Student> list = manager.getStudents();
setLog("get students success list.size()=" + list.size());
} catch (Exception e) {
e.printStackTrace();
}
}
private void setLog(String msg) {
log.append(msg + "\n");
tvLog.setText(log);
scrollView.fullScroll(View.FOCUS_DOWN);
}
}
完成,测试一下
首先安装服务端app并打开,然后安装客户端,调试
到此,全部完成。