简单的AIDL实现
main文件夹下新建aidl包,注意包名一定要相同,定义接口
package com.example.aidldemo.aidl;
parcelable Book;
//~~~~~~~~~~~~~~~~~~~~~~~~
package com.example.aidldemo.aidl;
import com.example.aidldemo.aidl.Book;//注意此处到导包
interface IBookManager {
List<Book>getBookList();
void addBook(in Book book);
}
同步一下,自动生成java文件
//服务端
public class BookMangerService extends Service {
private static final String TAG = "BookMangerService";
CopyOnWriteArrayList<Book> mBookList= new CopyOnWriteArrayList<Book>();
private Binder mBinder= new IBookManager.Stub(){
@Override
public List<Book> getBookList() throws RemoteException {
return mBookList;
}
@Override
public void addBook(Book book) throws RemoteException {
mBookList.add(book);
}
};
@Override
public void onCreate() {
super.onCreate();
mBookList.add(new Book(1,"android"));
mBookList.add(new Book(1,"ios"));
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
}
//~~~~~~~~~~设为远程
<service
android:name=".aidl.BookMangerService"
android:process=":remote"/>
//客户端
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
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.e(TAG, "onServiceConnected: getBookList type"
+bookList.getClass().getCanonicalName() );
Log.e(TAG, "onServiceConnected: "+bookList.toString() );
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent(this, BookMangerService.class);
bindService(intent,conn,Context.BIND_AUTO_CREATE);
}
@Override
protected void onDestroy() {
unbindService(conn);
super.onDestroy();
}
}
Binder机制详解
binder是android中的一个类,实现Ibinder接口,从IPC角度来说,Binder是Android中的一种跨进程通信方式,从Framework角度看,Binder是ServiceManager连接各种Manager(ActivityManager,WindowManager)的桥梁,从应用层来说,Binder是客户端和服务端通信的媒介,Binder底层细节复杂,暂时不深入研究。Android开发中,Binder主要用在Service中。包括AIDL和Messenger。Service很简单,不跨进程,binderService,Service的Onbinder里面返会一个binder对象,activity的onServiceConnect方法可以获取这个binder
所有可以在binder中传输的借口都要继承Interface接口 通过上面这个类可以了解binder的工作机制。
内部类Stub继承binder实现接口。当客户端服务端同一个进程时,方法调用不会走transact,跨进程时,就需要这个transact了,这个逻辑由Stub内部代理Proxy完成。下面说明几个主要方法
asInterface
将服务端binder对象转换成客户端aidl接口类型的对象。如果同一个进程,返回Stub,如果跨进程,返回系统封装后的Stub.proxy
asBinder
返回当前Binder对象
onTransact
Proxy#getBookList
Proxy#addBook
稍复杂的aidl实现&& aidl难点 线程相关
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private static final int MESSAGE_BOOK_ARRIVED = 1;
private ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mRemoteBookManager = IBookManager.Stub.asInterface(service);
try {
/**
* 难点,客户端调用远程服务的方法时,被调用的方法运行在服务端的binder线程池中,
* 同时,客户端线程挂起,如果服务端方法耗时,可能会导致anr,
* 服务端方法若耗时,也不必开线程
*
*/
List<Book> bookList = mRemoteBookManager.getBookList();
Log.e(TAG, "onServiceConnected: getBookList type"
+ bookList.getClass().getCanonicalName());
Log.e(TAG, "onServiceConnected: " + bookList.toString());
mRemoteBookManager.addBook(new Book(3, "android 进阶"));
Log.e(TAG, "onServiceConnected: " + mRemoteBookManager.getBookList().toString());
mRemoteBookManager.registerListener(mOnBookArrivedListener);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
IOnNewBookArrivedListener.Stub mOnBookArrivedListener =
new IOnNewBookArrivedListener.Stub() {
/**
* 服务端调用客户端listener方法,被调用方法运行在binder线程池中,
* 只不过是客户端的线程池,因此主线程更新ui
* 如果此方法耗时,要确保服务端运行在非ui线程
* @param newBook
* @throws RemoteException
*/
@Override
public void onNewBookArrived(Book newBook) throws RemoteException {
mHandler.obtainMessage(MESSAGE_BOOK_ARRIVED, newBook);
}
};
@SuppressLint("HandlerLeak")
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MESSAGE_BOOK_ARRIVED:
Log.e(TAG, "handleMessage: " + msg.obj);
break;
default:
break;
}
}
};
private IBookManager mRemoteBookManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent(this, BookMangerService.class);
bindService(intent, conn, Context.BIND_AUTO_CREATE);
}
@Override
protected void onDestroy() {
unbindService(conn);
super.onDestroy();
}
}
//~~~~~~~~~~~~~~~~~~~~
public class BookMangerService extends Service {
private static final String TAG = "BookMangerService";
private AtomicBoolean mIsServiceDestroyed = new AtomicBoolean(false);
CopyOnWriteArrayList<Book> mBookList = new CopyOnWriteArrayList<Book>();
// CopyOnWriteArrayList<IOnNewBookArrivedListener> mListenerList =
// new CopyOnWriteArrayList<IOnNewBookArrivedListener>();
/**
* RemoteCallbackList内部有个map结构专门用来保存所有aidl回调,
* key是IBinder,value是callback
*/
private RemoteCallbackList<IOnNewBookArrivedListener> mListenerList =
new RemoteCallbackList<IOnNewBookArrivedListener>();
private Binder mBinder = new IBookManager.Stub() {
@Override
public List<Book> getBookList() throws RemoteException {
return mBookList;
}
@Override
public void addBook(Book book) throws RemoteException {
mBookList.add(book);
}
@Override
public void registerListener(IOnNewBookArrivedListener listener) {
// if (!mListenerList.contains(listener)) {
// mListenerList.add(listener);
// } else {
// Log.e(TAG, "registerListener: alread exists");
// }
mListenerList.register(listener);
final int N = mListenerList.beginBroadcast();
Log.e(TAG, "registerListener:current size:" + N);
}
@Override
public void unregisterListener(IOnNewBookArrivedListener listener) {
// if (mListenerList.contains(listener)) {
// mListenerList.remove(listener);
// Log.e(TAG, "unregisterListener: unregister succeed");
// } else {
// Log.e(TAG, "unregisterListener: not found,can not unregister");
// }
boolean success = mListenerList.unregister(listener);
if (success) {
Log.d(TAG, "unregister success.");
} else {
Log.d(TAG, "not found, can not unregister.");
}
final int N = mListenerList.beginBroadcast();
mListenerList.finishBroadcast();
Log.d(TAG, "unregisterListener, current size:" + N);
}
};
@Override
public void onCreate() {
super.onCreate();
mBookList.add(new Book(1, "android"));
mBookList.add(new Book(1, "ios"));
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
private class ServiceWorker implements Runnable {
@Override
public void run() {
while (!mIsServiceDestroyed.get()) {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
int bookId = mBookList.size() + 1;
Book newBook = new Book(bookId, "new Book" + bookId);
onNewBookArrived(newBook);
}
}
}
private void onNewBookArrived(Book newBook) {
mBookList.add(newBook);
}
@Override
public void onDestroy() {
mIsServiceDestroyed.set(true);
super.onDestroy();
}
}
代码
https://github.com/gangjin1991/AndroidLearn/tree/master/aidldemo