p, li { white-space: pre-wrap; }

IPC即Inter-Process Communication,含义为进程间的通信或者跨进程通信,是指两个进程之间进行数据交换的过程。

android 中使用多进程

android中使用多进程很“简单”,简单到只需要一行代码就可以开启一个进程。但是真正要用好多进程还是不简单的。android中使用进程只需要在manfiest中进行申明,形式如下:

当然,也可以process的属性也可以设为以":"开始,例如

android:process =":remote"

表示运行在当前activity或者service的包名+.remote

Binder基础

什么是binder?

Binder是Android中的一种跨进程通信方式,Binder还可以理解为一种虚拟的物理设备,他的设备驱动是/dev/binder,该通信方式在Linux中没有。从Android Framework角度说,Binder是ManagerService的桥梁。从Android应用层角度来说,Binder是客户端和服务端调用的Binder对象,通过这个Binder对象,客户端就可以获取服务端提供的服务或者数据,这里的服务包括普通服务和基于AIDL的服务。

使用基础

本例将用aidl实现进程间的通信,同时服务端将会每隔5s给订阅图书信息的人发一条信息,同时客户端也可以其进行订阅和取消订阅操作。
首先先给出使用实例的整体框架视图,如图:

11-00-49.jpg

首先新建一个序列化的bean对象,命名为Book.java。

public class Book implements Parcelable {private int id;private String bookName;public Book(int id, String bookName) {this.id = id;this.bookName = bookName;}@Overridepublic String toString() {return "Book{" +"id=" + id +", bookName='" + bookName + '\'' +'}';}protected Book(Parcel in) {id = in.readInt();bookName = in.readString();}public static final Creator CREATOR = new Creator() {@Overridepublic Book createFromParcel(Parcel in) {return new Book(in);}@Overridepublic Book[] newArray(int size) {return new Book[size];}};@Overridepublic int describeContents() {return 0;}@Overridepublic void writeToParcel(Parcel dest, int flags) {dest.writeInt(id);dest.writeString(bookName);}}

然后新建aidl文件夹,并在里面添加Book.aidl文件,代码为:

// Book.aidl.aidlpackage reoger.hut.test2;parcelable Book;

记住一点,在aidl中,无论代码是否存在于同一个包中,都需要进行导入。
IBookManager.aidl的逻辑代码如下:

// IBookManager.aidlpackage reoger.hut.test2;import reoger.hut.test2.Book;import reoger.hut.test2.IOnNewBookArrivedArrivedListener;interface IBookManager {List getBookList();void addBook(in Book book);void registerListener(IOnNewBookArrivedArrivedListener listener);void unRegisterListener(IOnNewBookArrivedArrivedListener listener);}

然后是IOnNewBookArrivedArrivedListener.aidl的代码,如下:

// IOnNewBookArrivedArrivedListener.aidlpackage reoger.hut.test2;import reoger.hut.test2.Book;interface IOnNewBookArrivedArrivedListener {void onNewBookArrived(in Book newBook);}

接下来是我们服务端的实现,这里我采用的是通过一个service来实现,
BookManagerService.java的代码如下。

public class BookManagerService extends Service {private CopyOnWriteArrayList mBookList = new CopyOnWriteArrayList();private RemoteCallbackList mListeners = new RemoteCallbackList<>();private AtomicBoolean mIsServiceDestoryed = new AtomicBoolean(false);private Binder mBinder = new IBookManager.Stub() {@Overridepublic List getBookList() throws RemoteException {return mBookList;}@Overridepublic void addBook(Book book) throws RemoteException {mBookList.add(book);}/*** 注册监听* @param listener 监听对象* @throws RemoteException*/@Overridepublic void registerListener(IOnNewBookArrivedArrivedListener listener) throws RemoteException {mListeners.register(listener);Log.d("TAG", "增添监听成功");}@Overridepublic void unRegisterListener(IOnNewBookArrivedArrivedListener listener) throws RemoteException {mListeners.unregister(listener);Log.d("TAG", "增添监听成功");}};@Overridepublic void onCreate() {super.onCreate();mBookList.add(new Book(1, "android"));mBookList.add(new Book(2, "ios"));new Thread(new ServiceWorker()).start();}public BookManagerService() {}@Overridepublic IBinder onBind(Intent intent) {int check = checkCallingOrSelfPermission("reoger.hut.test2.permission.ACCESS_BOOK_SERVICE");if(check == PackageManager.PERMISSION_DENIED){Log.e("TAG","没有对应的权限,无法启动service");return null;}return mBinder;}private class ServiceWorker implements Runnable {@Overridepublic void run() {while (!mIsServiceDestoryed.get()) {try {Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}int bookId = mBookList.size() + 1;Book book = new Book(bookId, "new Book# " + bookId);onNewBookArrived(book);}}}private void onNewBookArrived(Book book) {mBookList.add(book);final int N = mListeners.beginBroadcast();for (int i = 0; i < N; i++) {IOnNewBookArrivedArrivedListener listener = mListeners.getBroadcastItem(i);Log.d("TAG", "onNew Book Arrived ,notify listener :");try {if (listener != null) {listener.onNewBookArrived(book);}} catch (RemoteException e) {e.printStackTrace();}}mListeners.finishBroadcast();}}

在manfiest文件中对service进行申明,并将其设置在一个单独的线程中运行,代码如下:

最后是我们的客户端代码,如下:

public class MainActivity extends AppCompatActivity {private Handler mHandler = new Handler(){@Overridepublic void handleMessage(Message msg) {switch (msg.what){case 0x66:Log.d("TAG","普天同庆 奔走相告"+msg.obj);break;default:super.handleMessage(msg);}}};private ServiceConnection connection = new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {bookManager = IBookManager.Stub.asInterface(service);List list = null;try {list = bookManager.getBookList();for (Book book : list) {Log.d("TAG",book.toString());}Book book = new Book(3,"android 开发艺术探索");bookManager.addBook(book);List list2 = bookManager.getBookList();for (Book book1 : list2) {Log.d("TAG","--- "+book1.toString());}bookManager.registerListener(mOnNewBookArrivedListener);} catch (RemoteException e) {e.printStackTrace();}}@Overridepublic void onServiceDisconnected(ComponentName name) {}};private IBookManager bookManager;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Intent intent = new Intent(this,BookManagerService.class);bindService(intent,connection, Context.BIND_AUTO_CREATE);}@Overrideprotected void onDestroy() {if(bookManager != null && bookManager.asBinder().isBinderAlive()){try {Log.d("TAG","正在停止服务...");bookManager.unRegisterListener(mOnNewBookArrivedListener);} catch (RemoteException e) {e.printStackTrace();}}unbindService(connection);super.onDestroy();}private IOnNewBookArrivedArrivedListener mOnNewBookArrivedListener = new IOnNewBookArrivedArrivedListener.Stub(){@Overridepublic void onNewBookArrived(Book newBook) throws RemoteException {mHandler.obtainMessage(0x66,newBook).sendToTarget();}};}

最后运行的结果主要通过打印的日志来显示。

11-12-51.jpg

通过日志信息,可以明确看到我们的服务端和客服端的确进行的数据交换,并且服务端每隔5s发送一个信息给客户端。

关于AIDL,有以下的几点需要特别的注意:

  • AIDL支持基本的数据类型(除short以外的数据类型),也支持String和CharSequence和Parcelable。对于List只支持ArrayList,对于Map只支持HshMap.
  • 如果AIDL文件中用到了自定义的Parcelable对象,必须新建一个和它同名的AIDL文件,并在其中声明它为Parcelable类型。可以参考上面的示例 。
  • AIDL中除了基本的数据类型,其他类型的参数必须标上方向:in,out或者inout,in表示输入型参数,out表示输出型参数,inout表示输入输出型参数。
  • 在AIDL中,只支持方法,不支持声明静态常量。
  • AIDL包结构在服务端和客户端必须保持一致,否运行会出错,这是因为客户端需要反序列化服务端中和AIDL接口相关的所有类。
  • AIDL方法是执行在服务端的Binder线程池中的。

更多相关文章

  1. Android(安卓)js交互 与 Html启动App
  2. Android代码混淆配置(Proguard文件解析)
  3. Android(安卓)NDK开发学习
  4. Android(安卓)init进程——源码分析
  5. Xposed框架之函数Hook学习
  6. Android(安卓)进程保活
  7. original-package
  8. Android高手进阶教程(八)之----Android(安卓)Widget开发案例(世
  9. Android核心分析(21)----Android应用框架之AndroidApplication

随机推荐

  1. Android(安卓)基础常见记录
  2. android中在代码中创建应用的快捷图标
  3. Android(安卓)实现永久保存数据的方法详
  4. android启动之子系统切换
  5. Android(安卓)ViewFlipper实现多个布局手
  6. Android(安卓)Studio gradle sync failed
  7. android 编译碰到的问题及解决办法:(ubun
  8. (android)向sdcard中添加文件出现Failed
  9. Android(安卓)IPC机制(三)使用AIDL实现
  10. Android开发环境及Hello World程序