AIDL-Android接口定义语言
一·
1.相比于Messenger AIDL可跨进程调用方法。
2.支持数据类型:
(1) Java 的原生基本类型(int, long, char, boolean, double等)
(2)String 和CharSequence
(3) ArrayList 和 HashMap ,里面的元素必须是AIDL支持的数据类型; 以上三种类型都不需要导入(import)
(4) AIDL 自动生成的接口 需要导入(import)
(5) 实现android.os.Parcelable 接口的类. 需要导入(import)
3.除了Java 的原生基本类型其他类型参数都需标明方向:in 输入 , out 输出, inout 出入输出。
4.建议吧所有一AIDL相关文件放在同一个文件夹下,方便复制到客户端,而且服务端可客户端AIDL包结构需保持一致,否则 无法反序列化成功
5.优点:功能强大,支持一对多并发通信,支持即时通信。
缺点:稍复杂,需做好线程同步。
使用场景:一对多且有RPC-远程方法调用 需求。
二,RemoteCallbackList系统用于管理跨进程listener,支持管理任意的AIDL
public class RemoteCallbackList<E extends IInterfaxc>
内部提供一个Map来管理这些AIDL,key为IBinder,value为Callback
ArrayMap<IBinder,Callback> mCallbacks = new ArrayMap<>();
当客户端注册listener时,Callback将listener的信息以IBinder为key存入mCallbacks,删除时也是找到此key对应的listener进行删除,因为跨进程生成的是相同的两个对象
三,创建AIDL文件,此代码复制粘贴即可顺利运行
1.创建Book类,IPC进程间通信(三)中已讲解,此处再创建一个aidl接口IOnNewBookArriveListener.aidl用于订阅书籍,同样会生成它自己的java类
package com.songfeng.aidlautocreate;
// Declare any non-default types here with import statements
//自定义类都需要显示的引入进来
import com.songfeng.aidlautocreate.Book;
//提供一个监听新书到达的接口
interface IOnNewBookArriveListener {
void onNewBookArrived(in Book book);
}
2.在IBookManger.aidl接口中增加注册和解注册方法,用于被远程调用,以实现某种功能
// IBookManager.aidl
package com.songfeng.aidlautocreate;
// Declare any non-default types here with import statements
import com.songfeng.aidlautocreate.Book;
import com.songfeng.aidlautocreate.IOnNewBookArriveListener;
interface IBookManager {
List<Book> getBookList();
void addBook(in Book book);
void registerLister(IOnNewBookArriveListener listener);
void unRegisterLister(IOnNewBookArriveListener listener);
}
3.创建BookManagerService用于管理AIDL文件,在其中实现Binder,并返回给客户端,以便在客户端调用Binder中的方法。
public class BookManagerService extends Service {
private static final String TAG = "BookManagerService";
private CopyOnWriteArrayList mBookList = new CopyOnWriteArrayList();
//注册和解注册多进程中的监听方法
private RemoteCallbackList mListenerList = new RemoteCallbackList();
@Override
public void onCreate() {
super.onCreate();
new Thread(new arrivedBookRunnable()).start();
}
//自动生成的java类,创建Binder,重写其方法,实现逻辑
private IBookManager.Stub mBinder = new IBookManager.Stub() {
@Override
public List<Book> getBookList() throws RemoteException {
return mBookList;
}
@Override
public void addBook(Book book) throws RemoteException {
if (!mBookList.contains(book)){
mBookList.add(book);
}
}
@Override
public void registerLister(IOnNewBookArriveListener listener) throws RemoteException {
mListenerList.register(listener);
}
@Override
public void unRegisterLister(IOnNewBookArriveListener listener) throws RemoteException {
mListenerList.unregister(listener);
}
};
//在这进行一个权限验证,只有客户端注册了此自定义权限才返回Binder给客户端
@Override
public IBinder onBind(Intent intent) {
int check = checkCallingOrSelfPermission("com.songfeng.aidlautocreate.permission.BookManagerService");
if (check == PackageManager.PERMISSION_DENIED){
return null;
}
return mBinder;
}
/**
* 开启线程每5秒添加一本新书并通知每一个注册了注册了监听方法的客户端
*/
private class arrivedBookRunnable implements Runnable{
@Override
public void run() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
int bookId = mBookList.size() + 1;
Book newBook = new Book(bookId,"Android : " + bookId);
//新书到达,启动通知
oOnNewBookArrived(newBook);
}
}
/**
* 通知每一个注册可监听方法IOnNewBookArriveListener的客户端,并回调到客户端的onNewBookArrived()
* @param newBook
*/
private void oOnNewBookArrived(Book newBook){
int N = mListenerList.beginBroadcast();
for (int i = 0; i < N; i++) {
IOnNewBookArriveListener listener =(IOnNewBookArriveListener) mListenerList.getBroadcastItem(i);
try {
listener.onNewBookArrived(newBook);
} catch (RemoteException e) {
e.printStackTrace();
}
}
mListenerList.finishBroadcast();
}
}
4.在客户端的连接方法中获取Binder,即可调用Binder中方法
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private static final int MSG_BOOK_ARRIVED = 1;
//自定义的AID文件,里面是一个接口
private IBookManager mIBookManager;
private List<Book> mBookList;
private MyHandler mHandler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mHandler = new MyHandler();
Intent intent = new Intent(MainActivity.this, BookManagerService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
private class MyHandler extends Handler {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case MSG_BOOK_ARRIVED:
Book book = (Book) msg.obj;
Toast.makeText(MainActivity.this, "新书 ID:"
+ book.getBookId() + ", 书名 :" + book.getBookName()
+ "已到达。", Toast.LENGTH_SHORT).show();
default:
break;
}
}
}
/**
* 监听图书到达,当服务调用新书到达的方法时就会回调到此方法
*/
private IOnNewBookArriveListener mBookArriveListener = new IOnNewBookArriveListener.Stub() {
@Override
public void onNewBookArrived(Book book) throws RemoteException {
mHandler.obtainMessage(MSG_BOOK_ARRIVED, book).sendToTarget();
}
};
/**
* 从服务中取出IBinder创建IBookManager
* public static com.songfeng.aidlautocreate.IBookManager asInterface(android.os.IBinder obj)
*/
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
IBookManager bookManager = IBookManager.Stub.asInterface(iBinder);
try {
Toast.makeText(MainActivity.this, "链接服务器成功", Toast.LENGTH_SHORT).show();
mIBookManager = bookManager;
mBookList = bookManager.getBookList();
Log.d(TAG, "BookList.size :" + mBookList.size());
//注册监听
bookManager.registerLister(mBookArriveListener);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
Toast.makeText(MainActivity.this, "服务器已断开,重连中...", Toast.LENGTH_SHORT).show();
Intent intent = new Intent(MainActivity.this, BookManagerService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
};
@Override
protected void onDestroy() {
super.onDestroy();
if (mIBookManager != null && mIBookManager.asBinder().isBinderAlive()) {
try {
mIBookManager.unRegisterLister(mBookArriveListener);
} catch (RemoteException e) {
e.printStackTrace();
}
unbindService(mConnection);
}
}
}
5.AndroidManifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
. . . . .
<service
android:name=".BookManagerService"
android:enabled="true"
android:exported="true"
android:process=":remote">
</service>
</manifest>