用个例子来解释,首先客户端调用服务端的方法添加书籍,然后服务端每5秒自己新添加一本书籍,并且通知客户端。
服务端
建一个AIDL文件,将暴露给客户端的这个接口在这个AIDL文件中声明,首先要创建一个Service用来监听客户端的连接请求,实现这个AIDL的接口即可。
1.创建AIDL文件,并声明所需要的方法,如下声明了四个方法。由于里面用到了Book这个类,要记得导包,及时在一个包下都需要导。
// IBookManager.aidl
package com.demo.nick.ipcstudy;
// Declare any non-default types here with import statements
import com.demo.nick.ipcstudy.Book;
import com.demo.nick.ipcstudy.IOnNewBookArrivedListener;
interface IBookManager {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
List<Book> getBookList();
void addBook(in Book book);
void registerListener(IOnNewBookArrivedListener listener);
void unregisterListener(IOnNewBookArrivedListener listener);
}
创建监听。
package com.demo.nick.ipcstudy;
// Declare any non-default types here with import statements
import com.demo.nick.ipcstudy.Book;
interface IOnNewBookArrivedListener {
void onNewBookArrived(in Book book);
}
2.编写Service
public class BookManagerService extends Service {
private static final String TAG = "BookManagerService";
private CopyOnWriteArrayList<Book> mBookList = new CopyOnWriteArrayList<>();//书本集合
//客户端监听器集合 beginBroadcast和finishBroadcast必须配对使用
private RemoteCallbackList<IOnNewBookArrivedListener> mListenerList=new RemoteCallbackList<>();
private AtomicBoolean mIsServiceDestoryed = new AtomicBoolean(false);//是否销毁的标记
// private CopyOnWriteArrayList<IOnNewBookArrivedListener> mListenerList = new CopyOnWriteArrayList<>();
//实现我们刚刚创建的AIDL接口
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) throws RemoteException {
// if (!mListenerList.contains(listener)) {
// mListenerList.add(listener);
// }else {
// Log.e(TAG, "already exists: " );
// }
mListenerList.register(listener);
int a=mListenerList.beginBroadcast();
Log.e(TAG, "当前监听器个数 "+a );
mListenerList.finishBroadcast();
// Log.e(TAG, "registerListener监听器个数: "+mListenerList.size());
}
@Override
public void unregisterListener(IOnNewBookArrivedListener listener) throws RemoteException {
// if(mListenerList.contains(listener)){
// mListenerList.remove(listener);
// Log.e(TAG, "解除成功: " );
// }else {
// Log.e(TAG, "没有可解除的: " );
// }
// Log.e(TAG, "当前监听器个数 "+mListenerList.size() );
// }
mListenerList.unregister(listener);
int a=mListenerList.beginBroadcast();
Log.e(TAG, "当前监听器个数 "+a );
mListenerList.finishBroadcast();
}
};
@Override
public void onCreate() {
super.onCreate();
mBookList.add(new Book(1, "android"));
mBookList.add(new Book(2, "ios"));
new Thread(new ServiceWorker()).start();
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
@Override
public void onDestroy() {
mIsServiceDestoryed.set(true);
super.onDestroy();
}
private void onNewBookArrived(Book book) throws RemoteException {
mBookList.add(book);
final int N=mListenerList.beginBroadcast();
for (int i=0;i<N;i++){
IOnNewBookArrivedListener listener=mListenerList.getBroadcastItem(i);
if (listener !=null) {
listener.onNewBookArrived(book);
}
}
mListenerList.finishBroadcast();
}
private class ServiceWorker implements Runnable{
@Override
public void run() {
//循环添加新书籍
while (!mIsServiceDestoryed.get()){
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
int bookId=mBookList.size()+1;
Book newBook=new Book(bookId,"new book"+bookId);
try {
onNewBookArrived(newBook
);
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
}
}
客户端
绑定服务端的Service,将服务端返回的Binder对象转换成AIDL接口所属的类型,就可以调用AIDL中的方法了。
public class BookManagerAty extends AppCompatActivity {
private static final String TAG = "BookManagerAty";
private static final int MESSAGE_NEW_BOOK_ARRIVED=1;
private IBookManager mRemoteBookManager;
private Handler mHandler=new Handler(){
@Override
public void handleMessage(Message msg) {
switch (msg.what){
case MESSAGE_NEW_BOOK_ARRIVED:
Log.e(TAG, "new BOOK: "+msg.obj );
break;
default:
super.handleMessage(msg);
}
}
};
private ServiceConnection mConnection=new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
IBookManager bookManager=IBookManager.Stub.asInterface(service);
try {
mRemoteBookManager=bookManager;
List<Book> list=bookManager.getBookList();
Log.e(TAG, "onServiceConnected: "+list.getClass().getCanonicalName());
Log.e(TAG, "onServiceConnected: "+list.toString() );
Book book=new Book(3,"java");
bookManager.addBook(book);
List<Book> newList=bookManager.getBookList();
Log.e(TAG, "onServiceConnected: "+newList.toString() );
bookManager.registerListener(mOnNewBookArrivedLisener);//注册监听
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
mRemoteBookManager=null;
Log.e(TAG, "onServiceDisconnected: " );
}
};
private IOnNewBookArrivedListener mOnNewBookArrivedLisener=new IOnNewBookArrivedListener.Stub() {
@Override
public void onNewBookArrived(Book book) throws RemoteException {
mHandler.obtainMessage(MESSAGE_NEW_BOOK_ARRIVED,book).sendToTarget();
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_book_manager_aty);
Intent intent=new Intent(this, BookManagerService.class);
bindService(intent,mConnection, Context.BIND_AUTO_CREATE);
}
@Override
protected void onDestroy() {
if (mRemoteBookManager!=null&&mRemoteBookManager.asBinder().isBinderAlive()){
Log.e(TAG, "onDestroy: "+mOnNewBookArrivedLisener );
try {
mRemoteBookManager.unregisterListener(mOnNewBookArrivedLisener);//解除监听
} catch (RemoteException e) {
e.printStackTrace();
}
}
unbindService(mConnection);
super.onDestroy();
}
}
这个时候我们的远程服务任何人都可以连接的,所以我们要做权限认证,
在Mainfest文件中自定义一个权限
<permission
android:name="com.demo.nick.ipcstudy.permission.TEST"
android:protectionLevel="normal"></permission>
然后修改Service中的onBind方法,
@Nullable
@Override
public IBinder onBind(Intent intent) {
//验证权限,自定义个权限,防止其他人连接我们的服务.
int check=checkCallingOrSelfPermission("com.demo.nick.ipcstudy.permission.TEST");
if (check== PackageManager.PERMISSION_DENIED){
//没有权限返回空,这样就绑定不了我们服务了。
return null;
}
return mBinder;
}
网友评论