众所周知,AIDL是进程间通信很常用的一种通信方式,很多时候你总会觉得它非常复杂而又乱
其实,你写一个demo你就懂了
而且最好的理解方式也是你自己亲手写一个demo!
下面我们通过一个最简单的demo来所说AIDL到底是怎么使用的
第一步 创建一个你要在进程间传递的数据类型,并且让这个数据类型implement安卓的两种序列化方式之一,Serializable或者Parcelable!否则,你的这个数据是没有办法在进程间通信传递的!
关于这Serializable和Parcelable的序列化,可以自己在百度了解一下
下面我建立了一个自己的数据类型book~ 继承Parcelable
项目结构如下
额,项目结构要注意,后面你建立aidl的文件项目结构要跟这个一样才行的
book.java的代码如下
package come.example.administrator.myapplication.aldl;
import android.os.Parcel;
import android.os.Parcelable;
public class book implements Parcelable {
private String bookname;
protected book(Parcel in) {
bookname = in.readString();
}
public book(String name){
bookname=name;
}
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];
}
};
public String getBookname() {
return bookname;
}
public void setBookname(String bookname) {
this.bookname = bookname;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(bookname);
}
}
在这里要注意下,其中@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(bookname);
}
都是你继承parceable自动实现的方法,这是用来将数据类型序列化的方法,而且这些方法还分三种,这里默认的只是in的方法,还有out和inout方法没有,感兴趣的可以自己百度一下然后建好这个数据类之后,我们开始第二步
第二步:创建第一步数据类型的映射aidl文件
具体步骤:先建立一个跟java文件夹同级的文件夹aidl,目录结构如下
当然,也有更简单的方法,那就是你鼠标右键new的时候有一个这样选项
选择这个选项,android studio会自动给你在java同级别建立aldl文件夹,还建立其中的包结构
刚才说过,在这第二步,我们要建立一个book的映射aidl文件,其实就是在java同级别的aidl文件夹下建立一个包路径名跟前面book.java一样的book.aidl
这里有些绕口,不过你看一下最后的目录结构就知道怎么回事了
可以看到,你要建立一个跟下面红色箭头book文件对应的,但是在aidl文件下下面的book.aidl文件
在这里要特别注意,这个文件路径要跟下面的book.java一样,包名都是一样的,注意到了吧
然后建立book.aidl文件之后,它的内容是这样的:
// bookd.aidl
package come.example.administrator.myapplication.aldl;
// Declare any non-default types here with import statements
parcelable book;
嗯,你看到了,其实就一句话,你加一句parcelable book就可以了第三步,建立具体操作数据,也就是操作那个book.java的aidl文件
在这里,我建造的是bookManger.aidl,里面只有两个方法addbook,和getListbook
目录结构如下:
内容如下
// bookManger.aidl
package come.example.administrator.myapplication;
import come.example.administrator.myapplication.aldl.book;
// Declare any non-default types here with import statements
interface bookManger {
/**
* 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);
void addbook(in book book);
List<book> getListBook();
}
在这里也有一点要注意,那就是import come.example.administrator.myapplication.aldl.book;
你要手动import 这个book进去这样,建造aidl方面工作就完成了,
第四步,生成系统用的aidl操作文件,其实就一个步骤,
你rebuild 一下你的工程,要是没有报错,你会发现在你工程的这个路径下会多出一个文件夹
要是发现这个文件夹那就可以了,然后不去管它
第五步 构造你通信用的服务端,
我在这里构造了一个service,这里路径没有规定,随意放就可以,我是这样放的
里面我是这样写的
package come.example.administrator.myapplication.aldl;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.annotation.Nullable;
import come.example.administrator.myapplication.bookManger;
import java.util.ArrayList;
import java.util.List;
public class aldlService extends Service {
private ArrayList<book> mbook;
/**
* 创建生成的本地 Binder 对象,实现 AIDL 制定的方法
*/
private IBinder mIBinder = new bookManger.Stub() {
@Override
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
}
@Override
public void addbook(book book) throws RemoteException {
mbook.add(book);
}
@Override
public List<book> getListBook() throws RemoteException {
return mbook;
}
};
@Nullable
@Override
public IBinder onBind(Intent intent) {
mbook = new ArrayList<>();
return mIBinder;
}
}
<service
android:name=".aldl.aldlService"
android:enabled="true"
android:exported="true"
android:process=":aidl"/>
第六步 创建你的客户端
其实也就是调用这个service,并且与这个service连接,拿到bindservice中的IBinder就可以了
我这里实现简单通信,代码如下
package come.example.administrator.myapplication.aldl;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
import come.example.administrator.myapplication.R;
import come.example.administrator.myapplication.bookManger;
import java.util.ArrayList;
public class AidlActivity extends AppCompatActivity {
ArrayList<book> mbook;
int bookindex=0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_aidl);
Intent intent1 = new Intent(getApplicationContext(), aldlService.class);
bindService(intent1, mConnection, BIND_AUTO_CREATE);
}
public void getClick(View v) throws RemoteException {
switch (v.getId()){
case R.id.addbook:
mAidl.addbook(new book("新书"+bookindex));
bookindex++;
Toast.makeText(getApplicationContext(),"新书添加成功",Toast.LENGTH_SHORT).show();
break;
case R.id.getbook:
mbook= (ArrayList<book>) mAidl.getListBook();
Toast.makeText(getApplicationContext(),"新书添加成功"+mbook.get(mbook.size()-1).getBookname(),Toast.LENGTH_SHORT).show();
break;
}
}
private bookManger mAidl;
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//连接后拿到 Binder,转换成 AIDL,在不同进程会返回个代理
mAidl = bookManger.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
mAidl = null;
}
};
}
其实要注意的就是,getclick是我按钮的点击事件,点击的时候,拿到下面mAidl,就可以使用我们刚才定义的bookManger定义的方法并且使用了