目录结构
Book.class
public class Book implements Parcelable {
public int bookId;
public String bookName;
public Book(int bookId, String bookName) {
this.bookId = bookId;
this.bookName = bookName;
}
private Book(Parcel in) {
bookId = in.readInt();
bookName = in.readString();
}
public static final Creator CREATOR = new Creator() {
@Override
public Book createFromParcel(Parcel in) {
return new Book(in);
}
@Override
public Book[] newArray(int size) {
return new Book[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(bookId);
dest.writeString(bookName);
}
}
Book.aidl
// Book.aidl
package com.example.yhadmin.aidldemo.bean;
// Declare any non-default types here with import statements
parcelable Book;//由于是自定义的Book 类型数据,需要声明为 parcelable 类型
IBookManager.aidl
// IBookManager.aidl
package com.example.yhadmin.aidldemo;
// Declare any non-default types here with import statements
import com.example.yhadmin.aidldemo.bean.Book;
interface IBookManager {
//除了基本数据类型,其他类型的参数都需要标上方向类型:in(输入), out(输出), inout(输入输出)
List getBookList();
void addBook(in Book book);
}
public class BookManagerService extends Service {
private static final String TAG = "BMS";
private CopyOnWriteArrayList mBookList = new CopyOnWriteArrayList();
//创建Binder 对象,即实现IBookManager 接口
private Binder mBinder = new IBookManager.Stub() {
@Override
public List 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(2,"Ios"));
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
}
public class ThirdActivity
extends AppCompatActivity
{
private static final String TAG = "BookManagerActivity";
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//将返回的 Binder 对象转换为 AIDL 接口
IBookManager bookManager = IBookManager.Stub.asInterface(service);
try {
//通过 AIDL 接口调用服务端的远程方法
List bookList = bookManager.getBookList();
Log.i(TAG,"query book list, list type:"+ bookList.getClass().getCanonicalName());
Log.i(TAG,"query book list: "+ bookList.toString());
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
public static void acrtionStart(Context context){
context.startActivity(new Intent(context, ThirdActivity.class));
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_third);
Button btn = findViewById(R.id.button);
final Intent intent = new Intent(this, BookManagerService.class);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
bindService(intent,mConnection,Context.BIND_AUTO_CREATE);
}
});
}
@Override
protected void onDestroy() {
unbindService(mConnection);
super.onDestroy();
}
}
public class ThirdActivity
extends AppCompatActivity
{
private static final String TAG = "BookManagerActivity";
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
IBookManager bookManager = IBookManager.Stub.asInterface(service);
try {
List bookList = bookManager.getBookList();
// Log.i(TAG,"query book list, list type:"+ bookList.getClass().getCanonicalName());
Log.i(TAG,"query book list: "+ bookList.toString());
Book newBook = new Book(3, "Android 开发艺术探索");
bookManager.addBook(newBook);
Log.i(TAG,"add book: "+ newBook);
List newList = bookManager.getBookList();
Log.i(TAG,"query book list: "+ newList.toString());
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
public static void acrtionStart(Context context){
context.startActivity(new Intent(context, ThirdActivity.class));
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_third);
Button btn = findViewById(R.id.button);
final Intent intent = new Intent(this, BookManagerService.class);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
bindService(intent,mConnection,Context.BIND_AUTO_CREATE);
}
});
}
@Override
protected void onDestroy() {
unbindService(mConnection);
super.onDestroy();
}
}
Log日志
// IOnNewBookArrivedListener.aidl
package com.example.yhadmin.aidldemo;
// Declare any non-default types here with import statements
import com.example.yhadmin.aidldemo.bean.Book;
interface IOnNewBookArrivedListener {
void onNewBookArrived(in Book newBook);
}
修改 IBookManager 代码,新增注册与注销监听器代码
// IBookManager.aidl
package com.example.yhadmin.aidldemo;
// Declare any non-default types here with import statements
import com.example.yhadmin.aidldemo.bean.Book;
import com.example.yhadmin.aidldemo.IOnNewBookArrivedListener;
interface IBookManager {
//除了基本数据类型,其他类型的参数都需要标上方向类型:in(输入), out(输出), inout(输入输出)
List getBookList();
void addBook(in Book book);
void registerListener(IOnNewBookArrivedListener listener);
void unregisterListener(IOnNewBookArrivedListener listener);
}
BookManagerService 代码
public class BookManagerService
extends Service
{
private static final String TAG = "BMS";
private CopyOnWriteArrayList mBookList = new CopyOnWriteArrayList();
private AtomicBoolean mIsServiceDestoryed = new AtomicBoolean(false);
//存储注册监听的客户端集合
private CopyOnWriteArrayList mListenerLiCopyOnWriteArrayList();
private Binder mBinder = new IBookManager.Stub() {
@Override
public List 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.d(TAG,"already exists.");
}
Log.d(TAG,"regeisterListener,size:"+mListenerList.size());
}
@Override
public void unregisterListener(IOnNewBookArrivedListener listener)
throws RemoteException
{
if (mListenerList.contains(listener)){
mListenerList.remove(listener);//移除监听
Log.d(TAG,"unregister listener succeed.");
}else {
Log.d(TAG,"not found, can not unregister.");
}
Log.d(TAG,"unregeisterListener,size:"+mListenerList.size());
}
};
@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;
}
//开启线程,5S 创建一本新书
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();
}
}
}
}
private void onNewBookArrived(Book newBook)
throws RemoteException
{
mBookList.add(newBook);//将新书添加到存储书本的集合中
Log.d(TAG,"onNewBookArrived, notify listeners:"+mListenerList.size());
for (int i = 0; i < mListenerList.size(); i++) {//便利存储的客户端监听集合
IOnNewBookArrivedListener listener = mListenerList.get(i);
Log.d(TAG,"onNewBookArrived, notify listeners:"+listener);
listener.onNewBookArrived(newBook);//通过接口回调方式通知客户端新书已到达
}
}
}
ThirdActivity 代码
public class ThirdActivity
extends AppCompatActivity
{
private static final String TAG = "BookManagerActivity";
private static final int MESSAGE_NEW_BOOK_ARRAIVED = 1;
private IBookManager mRemoteBookManager;
//构建监听器 Binder 对象
/**
* 当客户端发起远程请求时,由于当前线程会被挂起直至服务端进程返回数据,所以如果一个远程方法是很耗时的,
* 则不能在UI 线程中发起此远程请求,为了避免阻塞UI 线程出现ANR
* 由于服务端的Binder 方法运行在 Binder 的线程池中,所以 Binder 方法不管是否耗时都应该采用同步的方式去实现,因为它已经运行在一个线程中了
*/
private IOnNewBookArrivedListener mOnNewBookArrivedListener = new IOnNewBookArrivedListener.Stub() {
@Override
public void onNewBookArrived(Book newBook)
throws RemoteException
{
mHandler.obtainMessage(MESSAGE_NEW_BOOK_ARRAIVED, newBook)
.sendToTarget();
}
};
//防止Handler 泄漏
private static class ClientHandler extends Handler{
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MESSAGE_NEW_BOOK_ARRAIVED:
Log.d(TAG, "receive new book :" + msg.obj);
break;
default:
super.handleMessage(msg);
break;
}
}
}
private ClientHandler mHandler = new ClientHandler();
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//将返回的 IBinder 对象转成 AIDL 接口所属类型
mRemoteBookManager = IBookManager.Stub.asInterface(service);
try {
List bookList = mRemoteBookManager.getBookList();
// Log.i(TAG,"query book list, list type:"+ bookList.getClass().getCanonicalName());
Log.d(TAG, "query book list: " + bookList.toString());
Book newBook = new Book(3, "Android 开发艺术探索");
mRemoteBookManager.addBook(newBook);
Log.d(TAG, "add book: " + newBook);
List newList = mRemoteBookManager.getBookList();
Log.d(TAG, "query book list: " + newList.toString());
//注册监听器
mRemoteBookManager.registerListener(mOnNewBookArrivedListener);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
//连接断开,释放AIDL Binder对象
mRemoteBookManager = null;
Log.e(TAG, "Binder died.");
}
};
public static void acrtionStart(Context context) {
context.startActivity(new Intent(context, ThirdActivity.class));
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_third);
Button btn = findViewById(R.id.button);
final Intent intent = new Intent(this, BookManagerService.class);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
});
}
@Override
protected void onDestroy() {
//如果连接持续,并且Binder未死亡
if (mRemoteBookManager!=null&&mRemoteBookManager.asBinder().isBinderAlive()){
try {
Log.d(TAG,"unregister listener:"+mOnNewBookArrivedListener);
//注销监听
mRemoteBookManager.unregisterListener(mOnNewBookArrivedListener);
} catch (RemoteException e) {
e.printStackTrace();
}
}
unbindService(mConnection);
super.onDestroy();
}
}
public class BookManagerService
extends Service
{
.....
//注册
@Override
public void registerListener(IOnNewBookArrivedListener listener)
throws RemoteException
{
/* if (!mListenerList.contains(listener)){
mListenerList.add(listener);//添加监听
}else {
Log.d(TAG,"already exists.");
}*/
mListenerList.register(listener);
Log.d(TAG,"regeisterListener,current size:"+mListenerList.getRegisteredCallbackCount());
}
//解注册
@Override
public void unregisterListener(IOnNewBookArrivedListener listener)
throws RemoteException
{
/*if (mListenerList.contains(listener)){
mListenerList.remove(listener);//移除监听
Log.d(TAG,"unregister listener succeed.");
}else {
Log.d(TAG,"not found, can not unregister.");
}
*/
mListenerList.unregister(listener);
Log.d(TAG, "unregeisterListener,current size:"+mListenerList.getRegisteredCallbackCount());
}
private void onNewBookArrived(Book newBook)
throws RemoteException
{
mBookList.add(newBook);//将新书添加到存储书本的集合中
/* Log.d(TAG,"onNewBookArrived, notify listeners:"+mListenerList.size());
for (int i = 0; i < mListenerList.size(); i++) {//便利存储的客户端监听集合
IOnNewBookArrivedListener listener = mListenerList.get(i);
Log.d(TAG,"onNewBookArrived, notify listeners:"+listener);
listener.onNewBookArrived(newBook);//通过接口回调方式通知客户端新书已到达
}*/
final int N = mListenerList.beginBroadcast();
for (int i = 0; i < N; i++) {
IOnNewBookArrivedListener l = mListenerList.getBroadcastItem(i);
if (null!=l){
l.onNewBookArrived(newBook);
}
}
mListenerList.finishBroadcast();
}
....
}
注意: RemoteCallbackList 并不是一个List ,不能像 List 一样去操作它,遍历
RemoteCallbackList 必须要以下面的方式进行,其中 beginBroadcast 和 finishBroadcast 必须配套使用,哪怕我们仅仅是想要获取 RemoteCallbackList 中的元素个数
final int N = mListenerList.beginBroadcast();
for (int i = 0; i < N; i++) {
IOnNewBookArrivedListener l = mListenerList.getBroadcastItem(i);
if (null!=l){
l.onNewBookArrived(newBook);
}
}
mListenerList.finishBroadcast();
@Override
public List getBookList()
throws RemoteException
{
SystemClock.sleep(5000);
return mBookList;
}
连续单机几次,就出现了 ANR
如要避免这种 ANR, 只需把调用放在非UI 线程即可
public void onButtonClick(View view) {
new Thread(new Runnable() {
@Override
public void run() {
if (mRemoteBookManager != null) {
try {
List newList = mRemoteBookManager.getBookList();
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
}).start();
}
同理,当远程服务端需要调用客户端的 listener 中的方法时,被调用的方法运行在客户端的 Binder 池中,故我们同样不可以在服务端调用客户端耗时方法,比如针对 BookManagerService 的 onNewBookArrived 方法,在它内部调用了客户端的 IOnNewBookArrivedListener 中的 onNewBookArrived 方法,如果客户端的这个 onNewBookArrived 方法比较耗时的话,确保 BookManagerService 的onNewBookArrived 运行在非 UI 线程中,否则将导致服务端无法响应
private void onNewBookArrived(Book newBook)
throws RemoteException
{
mBookList.add(newBook);//将新书添加到存储书本的集合中
/* Log.d(TAG,"onNewBookArrived, notify listeners:"+mListenerList.size());
for (int i = 0; i < mListenerList.size(); i++) {//便利存储的客户端监听集合
IOnNewBookArrivedListener listener = mListenerList.get(i);
Log.d(TAG,"onNewBookArrived, notify listeners:"+listener);
listener.onNewBookArrived(newBook);//通过接口回调方式通知客户端新书已到达
}*/
final int N = mListenerList.beginBroadcast();
for (int i = 0; i < N; i++) {
IOnNewBookArrivedListener l = mListenerList.getBroadcastItem(i);
if (null!=l){
l.onNewBookArrived(newBook);
}
}
mListenerList.finishBroadcast();
}
public class ThirdActivity
extends AppCompatActivity
{
private static final String TAG = "BookManagerActivity";
private static final int MESSAGE_NEW_BOOK_ARRAIVED = 1;
private IBookManager mRemoteBookManager;
//构建监听器 Binder 对象
/**
* 当客户端发起远程请求时,由于当前线程会被挂起直至服务端进程返回数据,所以如果一个远程方法是很耗时的,
* 则不能在UI 线程中发起此远程请求,为了避免阻塞UI 线程出现ANR
* 由于服务端的Binder 方法运行在 Binder 的线程池中,所以 Binder 方法不管是否耗时都应该采用同步的方式去实现,因为它已经运行在一个线程中了
*/
private IOnNewBookArrivedListener mOnNewBookArrivedListener = new IOnNewBookArrivedListener.Stub() {
@Override
public void onNewBookArrived(Book newBook)
throws RemoteException
{
mHandler.obtainMessage(MESSAGE_NEW_BOOK_ARRAIVED, newBook)
.sendToTarget();
}
};
//防止Handler 泄漏
private static class ClientHandler
extends Handler
{
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MESSAGE_NEW_BOOK_ARRAIVED:
Log.d(TAG, "receive new book :" + msg.obj);
break;
default:
super.handleMessage(msg);
break;
}
}
}
private ClientHandler mHandler = new ClientHandler();
//DeathRecipient 方式
private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
@Override
public void binderDied() {
if (mRemoteBookManager==null)
return;
mRemoteBookManager.asBinder().unlinkToDeath(mDeathRecipient,0);
mRemoteBookManager=null;
//重新绑定服务
Intent intent = new Intent(ThirdActivity.this, BookManagerService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
};
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//将返回的 IBinder 对象转成 AIDL 接口所属类型
mRemoteBookManager = IBookManager.Stub.asInterface(service);
//客户端绑定远程服务成功后,给binder 设置死亡代理
try {
mRemoteBookManager.asBinder().linkToDeath(mDeathRecipient,0);
} catch (RemoteException e) {
e.printStackTrace();
}
try {
List bookList = mRemoteBookManager.getBookList();
// Log.i(TAG,"query book list, list type:"+ bookList.getClass().getCanonicalName());
Log.d(TAG, "query book list: " + bookList.toString());
Book newBook = new Book(3, "Android 开发艺术探索");
mRemoteBookManager.addBook(newBook);
Log.d(TAG, "add book: " + newBook);
List newList = mRemoteBookManager.getBookList();
Log.d(TAG, "query book list: " + newList.toString());
//注册监听器
mRemoteBookManager.registerListener(mOnNewBookArrivedListener);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
//连接断开,释放AIDL Binder对象
mRemoteBookManager = null;
Log.e(TAG, "Binder died.");
}
};
public static void acrtionStart(Context context) {
context.startActivity(new Intent(context, ThirdActivity.class));
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_third);
Button btn = findViewById(R.id.button);
final Intent intent = new Intent(this, BookManagerService.class);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
});
}
@Override
protected void onDestroy() {
//如果连接持续,并且Binder未死亡
if (mRemoteBookManager != null && mRemoteBookManager.asBinder()
.isBinderAlive())
{
try {
Log.d(TAG, "unregister listener:" + mOnNewBookArrivedListener);
//注销监听
mRemoteBookManager.unregisterListener(mOnNewBookArrivedListener);
} catch (RemoteException e) {
e.printStackTrace();
}
}
unbindService(mConnection);
super.onDestroy();
}
}
permission 验证? @Nullable
@Override
public IBinder onBind(Intent intent) {
int check = checkCallingOrSelfPermission("com.example.yhadmin.aidldemo.permission.ACCESS_BOOK_SERVICE");
if (check == PackageManager.PERMISSION_DENIED) {
return null;
}
return mBinder;
}
其次包名必须以 “com.example.yhadmin” 开始,否则调用服务端的方法会失败
private Binder mBinder = new IBookManager.Stub() {
@Override
public List getBookList()
throws RemoteException
{
SystemClock.sleep(5000);
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.d(TAG,"already exists.");
}*/
mListenerList.register(listener);
Log.d(TAG,
"regeisterListener,current size:" + mListenerList.getRegisteredCallbackCount());
}
//解注册
@Override
public void unregisterListener(IOnNewBookArrivedListener listener)
throws RemoteException
{
/*if (mListenerList.contains(listener)){
mListenerList.remove(listener);//移除监听
Log.d(TAG,"unregister listener succeed.");
}else {
Log.d(TAG,"not found, can not unregister.");
}
*/
mListenerList.unregister(listener);
Log.d(TAG,
"unregeisterListener,current size:" + mListenerList.getRegisteredCallbackCount());
}
@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException
{
int check = checkCallingOrSelfPermission("com.example.yhadmin.aidldemo.permission.ACCESS_BOOK_SERVICE");
if (check == PackageManager.PERMISSION_DENIED) {
return false;
}
String packageName = null;
String[] packages = getPackageManager().getPackagesForUid(getCallingUid());
if (packages != null && packages.length > 0) {
packageName=packages[0];
}
if (!packageName.startsWith("com.example.yhadmin")){
return false;
}
return super.onTransact(code, data, reply, flags);
}
};
还可以为Service 指定 android:permission属性等进行权限验证