Android中使用AIDL完成不同进程间的通信
使用AIDL完成不同应用程序之间的数据通信,本人也是菜鸟一枚,错漏的地方请大家海涵。话不多说,下面开始讲解。
首先,建立两个工程,一个作为服务端,一个作为客户端。
服务端的目录结构如下:
作为服务端就要能够接受来自客户端的请求,因此服务端需要向外界暴露出一些接口让客户端调用。
大概思路是服务端首先要创建一个Service用来监听客户端的请求,然后创建一个AIDL文件,将暴露给客户端的接口在这个AIDL文件里声明,最后在Service中实现这个AIDL接口即可。
首先声明AIDL文件,使用Android Studio在com.xsx.aidl_service里新建一个AIDL文件,AS会自动在src/main目录下面为我们建立一个放置AIDL文件的文件夹,之后所有的AIDL文件都放在这里面。
IBookManager.aidl的内容如下:
package com.xsx.aidl_service;
import com.xsx.aidl_service.Book;
interface IBookManager {
List<Book> getBookList();
void addBook(in Book book);
}
因为该aidl文件里使用了自定义类Book,所以也需要为Book建立Book.aidl文件。比较简单,如下:
package com.xsx.aidl_service;
parcelable Book;
注意此时AS还不会帮我们自动建立IBookManager.java文件,我们需要编译一下工程。之后才可以在Service中使用IBookManager。
接着在com.xsx.aidl_service包下建立BookManagerService.java文件
public class BookManagerService extends Service{
//支持并发读写操作的list
private CopyOnWriteArrayList<Book> bookList=new CopyOnWriteArrayList<Book>();
//接口的调用就包含在Binder里面了,当客户端得到该Binder时就可以调用服务器的方法
private Binder binder=new IBookManager.Stub(){
@Override
public List<Book> getBookList() throws RemoteException {
return bookList;
}
@Override
public void addBook(Book book) throws RemoteException {
bookList.add(book);
}
};
@Override
public void onCreate() {
super.onCreate();
bookList.add(new Book(1,"Android 编程"));
bookList.add(new Book(2,"Java 特种兵"));
}
@Override
public IBinder onBind(Intent intent) {
//客户端绑定时得到Binder对象
return binder;
}
}
在服务被绑定的时候,返回我们定义的Binder对象,在Binder对象里可以实现方法的具体逻辑。
上面我在onCreate方法里向列表中添加了两本书,下面我要在客户端将列表的内容输出。
另外,切记一点,建立好Service后要在Manifest中声明;
记住服务一定要有intent-filter,否则找不到
<service android:name=".BookManagerService">
<intent-filter>
<action android:name="com.xsx.aidl_service.BookManagerService"/>
</intent-filter>
</service>
android:name的值就是待会在客户端访问服务端时需要用到。
到此,服务端的内容写好,接下来写客户端。
客户端的目录结构如下:
首先,将服务端的aidl文件夹整个拷贝到客户端,内容不必改动,因为无论是服务端还是客户端用的aidl接口都是一样的。如果有自定义类型的文件,如Book.java,则在客户端的src/main/java目录下建立和客户端相同包名的包,并将自定义类型的文件复制进去。
OK,一样,编译一下工程。接下来编写发送请求的客户端代码,如下:
public class BookManagerActivity extends AppCompatActivity {
private static final String TAG ="BookManagerActivity" ;
private ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
IBookManager bookManager = IBookManager.Stub.asInterface(service);
try {
List<Book> bookList=bookManager.getBookList();
Log.i(TAG, "bookList=" + bookList);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//通过Intent绑定服务端
Intent intent = new Intent("com.xsx.aidl_service.BookManagerService");
bindService(intent, conn, Context.BIND_AUTO_CREATE);
}
@Override
protected void onDestroy() {
unbindService(conn);
super.onDestroy();
}
}
首先我们在onCreate方法中绑定服务。
服务绑定成功后,会在onServiceConnected方法中返回一个Binder对象,此时将这个对象转化为我们的IBookManager接口。
IBookManager bookManager = IBookManager.Stub.asInterface(service);
而后,我们就可以通过这个对象去调用之前在服务中实现的方法。
List<Book> bookList=bookManager.getBookList();
将程序运行运行,可以发现Log打印出了之前在服务端添加的两本书的信息,进程间的通信就完成了。