Android开发:AIDL系列
程序员文章站
2022-04-07 19:37:48
一、回顾:
上一篇文章实现:客户端app从服务端app获取数据、添加数据。
二、目的:
本文主要实现:服务端数据更新的时候(本例中即:有新书被添加的时候)告知客户端。类似通知...
一、回顾:
上一篇文章实现:客户端app从服务端app获取数据、添加数据。
二、目的:
本文主要实现:服务端数据更新的时候(本例中即:有新书被添加的时候)告知客户端。类似通知功能。
2.1、如何实现:简而言之,如下。
1、服务端新建线程:每5秒新增一本书。
2、客户端在服务端注册实时监听服务端的添加方法。
2.2、服务端具体如下:
1、新建一个监听接口,由于监听是通过AIDL接口传输调用。所以监听接口也是AIDL接口。
// IOnNewBookArrivedListener.aidl package haibo.com.servelapp; // Declare any non-default types here with import statements import haibo.com.servelapp.Book; interface IOnNewBookArrivedListener { /** * Demonstrates some basic types that you can use as parameters * and return values in AIDL. */ void OnNewBookArrived(in Book newBook); }注释:此方法为IOnNewBookArrivedListener.aidl而不是IOnNewBookArrivedListener.java。当有新书到的时候,调用OnNewBookArrived方法。
2、建立进程间通信的桥梁。在上一个例子中AIDL接口中添加两个方法,注册监听及取消监听。
// IBookManager.aidl package haibo.com.servelapp; // Declare any non-default types here with import statements import haibo.com.servelapp.Book; import haibo.com.servelapp.IOnNewBookArrivedListener; interface IBookManager { List注释:第6行代码务必需要手动添加!getBookList(); void addBook(in Book book); void registerListener(IOnNewBookArrivedListener listener); void unregisterListener(IOnNewBookArrivedListener listener); }
import haibo.com.servelapp.IOnNewBookArrivedListener;
3、修改BookManagerService服务代码,使实现接口的两个新增方法registerListener和unregisterListener。
package haibo.com.servelapp.service; import android.app.Service; import android.content.Intent; import android.os.Binder; import android.os.IBinder; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.util.Log; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.atomic.AtomicBoolean; import haibo.com.servelapp.Book; import haibo.com.servelapp.IBookManager; import haibo.com.servelapp.IOnNewBookArrivedListener; public class BookManagerService extends Service { private CopyOnWriteArrayListmBookList = new CopyOnWriteArrayList<>(); //之所以用列表,因为每个客户端都需要注册一个监听在服务端 // private CopyOnWriteArrayList mlistener = new CopyOnWriteArrayList<>(); private RemoteCallbackList mListenerList = new RemoteCallbackList<>(); private AtomicBoolean flag = new AtomicBoolean(); 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 (!mlistener.contains(listener)) // mlistener.add(listener); mListenerList.register(listener); Log.e("BookManagerService", "registerListener success"+mListenerList.getRegisteredCallbackCount()); } @Override public void unregisterListener(IOnNewBookArrivedListener listener) throws RemoteException { // if (mlistener.contains(listener)) // mlistener.remove(listener); // flag = false; mListenerList.unregister(listener); Log.e("BookManagerService", "unregisterListener success"+mListenerList.getRegisteredCallbackCount()); } }; public BookManagerService() { } @Override public void onCreate() { super.onCreate(); mBookList.add(new Book(1, "Android")); mBookList.add(new Book(2, "Ios")); //这种方式的缺点就是每次有个一个客户端进来,就会生成一个新的服务端线程 new Thread(new Runnable() { @Override public void run() { while (!flag.get()) { try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } int bookId = mBookList.size() + 1; Book newBook = new Book(bookId, "newBook" + bookId); Log.e("BookManagerService", "newBook" + bookId); mBookList.add(newBook); final int N = mListenerList.beginBroadcast(); for (int i=0;i 注释:第41-56行,实现了注册监听和解除注册监听方法。 ;i++){>重点1:其中第24行使用的列表不是常规的List的接口。两个疑问:一是而且此处使用list而不是一个通常意义上的监听,是因为服务端可以面向多个客户端。二是使用RemoteCallbackList,因为常规的ArrayList不能实现注册监听的时候反序列化的对象和解除注册时候的反序列化对象是同一个。每次反序列化都是创建一个新对象的过程。无法解除监听。
private RemoteCallbackListmListenerList = new RemoteCallbackList<>(); 4、新建线程:每五秒新建一本书。代码如下:
new Thread(new Runnable() { @Override public void run() { while (!flag.get()) { try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } int bookId = mBookList.size() + 1; Book newBook = new Book(bookId, "newBook" + bookId); Log.e("BookManagerService", "newBook" + bookId); mBookList.add(newBook); final int N = mListenerList.beginBroadcast(); for (int i=0;i注释:其中第15-26行代码为查看是否有客户端注册监听,如果有,则执行客户端监听的onNewBookArrived方法: ;i++){>final int N = mListenerList.beginBroadcast(); for (int i=0;i重点2:上述代码第一行和最后一行必须成对匹配使用。如果不使用,第一行,则会造成无法获取到监听者对象IOnNewBookArrivedListener。 ;i++){>2.3、客户端具体实现:
除了需要将服务端的AIDL代码完整复制到客户端外,还需要做如下操作。
1、客户端代码如下:
package haibo.com.clientapp; import android.app.Activity; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.os.RemoteException; import android.text.TextUtils; import android.util.Log; import android.view.View; import android.widget.EditText; import android.widget.TextView; import java.util.List; import haibo.com.servelapp.Book; import haibo.com.servelapp.IBookManager; import haibo.com.servelapp.IOnNewBookArrivedListener; public class MainActivity extends Activity { private TextView textView,newbook; private EditText edit_query; private IBookManager bookManager; private static int count = 0; private Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { switch (msg.what){ case 1: Log.e("MainActivity","receive new book:"+msg.obj.toString()); newbook.setText("receive new book:"+msg.obj.toString()); break; } } }; private ServiceConnection connection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { bookManager = IBookManager.Stub.asInterface(service); try { List注释:其中第65-73行,客户端实现了接口IOnNewBookArrivedListener,表明服务端有更新的时候,客户端需要做什么。list = bookManager.getBookList(); count = list.size(); textView.setText("getBookList结果是:"+list.toString()); Log.e("MainActivity",list.toString()); bookManager.registerListener(mIOnNewBookArrivedListener); } catch (RemoteException e) { e.printStackTrace(); } } @Override public void onServiceDisconnected(ComponentName name) { bookManager = null; } }; private IOnNewBookArrivedListener mIOnNewBookArrivedListener = new IOnNewBookArrivedListener.Stub() { @Override public void OnNewBookArrived(Book newBook) throws RemoteException { Message msg = Message.obtain(); msg.obj = newBook; msg.what = 1; handler.sendMessage(msg); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); textView = (TextView) findViewById(R.id.booklist); edit_query = (EditText) findViewById(R.id.edit_query); newbook = (TextView) findViewById(R.id.newbook); //初始化启动service Intent intent = new Intent("haibo.com.servelapp.service.BookManagerService"); bindService(intent,connection, Context.BIND_AUTO_CREATE); } @Override protected void onDestroy() { super.onDestroy(); try { bookManager.unregisterListener(mIOnNewBookArrivedListener); } catch (RemoteException e) { e.printStackTrace(); } unbindService(connection); } public void addBook(View view) throws RemoteException { //添加一本书并展示 String str = edit_query.getText().toString(); if (!TextUtils.isEmpty(str)){ count++; bookManager.addBook(new Book(count,str)); } List newlist = bookManager.getBookList(); textView.setText("新getBookList结果是:"+newlist.toString()); Log.e("MainActivity",newlist.toString()); } } private IOnNewBookArrivedListener mIOnNewBookArrivedListener = new IOnNewBookArrivedListener.Stub() { @Override public void OnNewBookArrived(Book newBook) throws RemoteException { Message msg = Message.obtain(); msg.obj = newBook; msg.what = 1; handler.sendMessage(msg); } };第31-40行,由于服务端在子线程中执行发送消息,客户端也需要通过handler发送消息给主线程来更新UI。private Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { switch (msg.what){ case 1: Log.e("MainActivity","receive new book:"+msg.obj.toString()); newbook.setText("receive new book:"+msg.obj.toString()); break; } } };关于注册和解除监听:第53行:在bindService建立连接的时候注册监听。
bookManager.registerListener(mIOnNewBookArrivedListener);第91行:在MainActivity销毁的时候解除监听,并解除绑定service。@Override protected void onDestroy() { super.onDestroy(); try { bookManager.unregisterListener(mIOnNewBookArrivedListener); } catch (RemoteException e) { e.printStackTrace(); } unbindService(connection); }至此服务端在更新数据的时候,会主动告知已经在服务端注册监听的客户端,客户端将获得数据并更新UI。当客户端销毁的时候,会解除监听,解除服务绑定。
本章,完。AIDL,完。
下一篇: Android流行框架整理
推荐阅读