从事 Android 开发也跨过了1年的时间了,在之前的工作、开发中,功能实现、第三方框架使用、Copy 网上的代码占据了我的大部分开发时间。学着学着就开始发现个人的综合能力并没有得到有效的提升,虽然大部分的功能都能通过查找来实现,但离开里网络、或者说涉及到底层实现就真的有点懵逼了。经验的积累很重要,个人的学习充电更为重要。
对于 Android 开发来说,进程间的通信是一门大课。总会有许许多多的场景让你需要使用到它。Android 中是不允许跨进程之间直接调用对方的资源的。而AIDL 是帮助我们跨进程进行通信的方式之一。AIDL是 Android Interface definition language 的简称。通过名字就能知道,它是一种跨进程间的接口定义语言,类似网络请求的 C(客户端)/S(服务器端)。 通过它我们可以定义跨进程的接口使用。 下面我们来看看如何简单的使用 AIDL 来实现进程间通信。
1、创建 AIDL 文件来创建我们的服务端。在 app 包下创建一个 aidl 包,在包内创建一个与项目包名一致的子包。并在子包中创建一个 IBookAidl.aidl 文件
在这个 IBookAidl.aidl 文件中有 getBooks() addBook()方法。
package com.mrj.zy.multiprocessdemo;
import com.mrj.zy.multiprocessdemo.Book;
interface IBookAidl {
List<Book> getBooks();//获取所有的书籍
void addGame(in Book book);//添加书籍
}
由于在
IBookAidl.aidl 中我们使用了 Book 这个类,它实现了 Parcelable 。所以我们应该再创建一个 Book.aidl :
package com.mrj.zy.multiprocessdemo;
parcelable Book;
2、在项目中创建一个 AidlService (服务端)继承自 Service 来实现 aidl 文件中的方法。
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
public class AidlService extends Service{
//初始化书籍集合
private CopyOnWriteArrayList<Book> books=new CopyOnWriteArrayList<>();
//通过Aidl的Stub内部类实现跨进程接口 来获得一个Binder对象
private Binder mBinder=new IBookAidl.Stub() {
@Override
public List<Book> getBooks() throws RemoteException {
return books;
}
@Override
public void addGame(Book book) throws RemoteException {
books.add(book);
}
};
@Override
public void onCreate() {
super.onCreate();
books.add(new Book("Android 从入门到放弃","就是这么神奇的入门与放弃学"));
books.add(new Book("Http 协议","很难的一个知识点啊"));
}
@Override
public IBinder onBind(Intent intent) {
//返回的就是我们从跨进程中获取的Binder对象
return mBinder;
}
}
3、在客户端进程中绑定服务端,将得到的 Binder 对象转换为 AIDL 接口,这样我们就可以在我们的进程中调用 Aidl 接口中的方法了。
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.widget.Button;
import android.widget.EditText;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
public class AidlActivity extends AppCompatActivity {
@BindView(R.id.first_number)
EditText firstNumber; //书名
@BindView(R.id.second_number)
EditText secondNumber; //内容
@BindView(R.id.add_for_result)
Button addForResult; //添加书籍
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_aidl);
ButterKnife.bind(this);
}
//初始化一个ServiceConnection对象并且重写里面的方法
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//通过IBinder对象得到一个跨进程的AIDL对象
IBookAidl iBookAidl = IBookAidl.Stub.asInterface(service);
//新建一本书
Book book = new Book(firstNumber.getText().toString(), secondNumber.getText().toString());
try {
//通过调用 AIDL 的方法添加书籍
iBookAidl.addGame(book);
//遍历书籍 并且打印出每本书的名字与内容
for (Book b:iBookAidl.getBooks()) {
Log.d("RJie", "书名: "+b.bookName+" 简介 :"+b.bookDescribe);
}
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
@OnClick(R.id.add_for_result)
public void onClick() {
//与服务端进行绑定
Intent aidlIntent = new Intent(this, AidlService.class);
bindService(aidlIntent,connection, Context.BIND_AUTO_CREATE);
}
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(connection);//解绑服务端
}
}
布局文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<EditText
android:id="@+id/first_number"
android:hint="请输入书名"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<EditText
android:id="@+id/second_number"
android:hint="请输入简介"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<Button
android:id="@+id/add_for_result"
android:text="相加"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
还有 Book 这个实体类:
import android.os.Parcel;
import android.os.Parcelable;
public class Book implements Parcelable {
public String bookName;
public String bookDescribe;
public Book(String bookName, String bookDescribe) {
this.bookName = bookName;
this.bookDescribe = bookDescribe;
}
protected Book(Parcel in) {
bookName = in.readString();
bookDescribe = in.readString();
}
public static final Creator<Book> CREATOR = new Creator<Book>() {
@Override
public Book createFromParcel(Parcel in) {
return new Book(in);
}
@Override
public Book[] newArray(int size) {
return new Book[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(bookName);
dest.writeString(bookDescribe);
}
}
这样一个大体的使用 AIDL 来实现跨进程通信的例子就完成了。