zoukankan      html  css  js  c++  java
  • Android进阶-IPC机制

    一.背景:

    一个应用默认只在一个进程中运行,当两个进程需要进行通信时不能像平常一样传递数据,因为每个进程都有它自己的虚拟地址空间,两个进程虽然有相同的虚拟地址,但是这两个虚拟地址被映射到的实际的物理地址却不尽相同,这时就需要有进程间通信机制。在Android下,常见的IPC机制有:
    1. Bundle
    2. 文件共享
    3. Messager
    4. AIDL
    5. ContentProvider
    6. Socket
    这里主要记录AIDL的一些知识。

    二.AIDL的使用:

    1. 创建接口
    在/src/main/aidl/pacage name/下新建IBookManager.aidl

    1 package com.dhn.learnaidl;
    2 
    3 interface IBookManager {
    4 List<String> getBookList();
    5 void addBook(String book);
    6 }

    sync工程,
    自动生成IBookManager.java:

      1 package com.dhn.learnaidl;
      2 
      3 public interface IBookManager extends android.os.IInterface {
      4     /**
      5      * Local-side IPC implementation stub class.
      6      */
      7     public static abstract class Stub extends android.os.Binder implements com.dhn.learnaidl.IBookManager {
      8         private static final java.lang.String DESCRIPTOR = "com.dhn.learnaidl.IBookManager";
      9 
     10         /**
     11          * Construct the stub at attach it to the interface.
     12          */
     13         public Stub() {
     14             this.attachInterface(this, DESCRIPTOR);
     15         }
     16 
     17         /**
     18          * Cast an IBinder object into an com.dhn.learnaidl.IBookManager interface,
     19          * generating a proxy if needed.
     20          */
     21         public static com.dhn.learnaidl.IBookManager asInterface(android.os.IBinder obj) {
     22             if ((obj == null)) {
     23                 return null;
     24             }
     25             android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
     26             if (((iin != null) && (iin instanceof com.dhn.learnaidl.IBookManager))) {
     27                 return ((com.dhn.learnaidl.IBookManager) iin);
     28             }
     29             return new com.dhn.learnaidl.IBookManager.Stub.Proxy(obj);
     30         }
     31 
     32         @Override
     33         public android.os.IBinder asBinder() {
     34             return this;
     35         }
     36 
     37         @Override
     38         public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
     39             switch (code) {
     40                 case INTERFACE_TRANSACTION: {
     41                     reply.writeString(DESCRIPTOR);
     42                     return true;
     43                 }
     44                 case TRANSACTION_getBookList: {
     45                     data.enforceInterface(DESCRIPTOR);
     46                     java.util.List<java.lang.String> _result = this.getBookList();
     47                     reply.writeNoException();
     48                     reply.writeStringList(_result);
     49                     return true;
     50                 }
     51                 case TRANSACTION_addBook: {
     52                     data.enforceInterface(DESCRIPTOR);
     53                     java.lang.String _arg0;
     54                     _arg0 = data.readString();
     55                     this.addBook(_arg0);
     56                     reply.writeNoException();
     57                     return true;
     58                 }
     59             }
     60             return super.onTransact(code, data, reply, flags);
     61         }
     62 
     63         private static class Proxy implements com.dhn.learnaidl.IBookManager {
     64             private android.os.IBinder mRemote;
     65 
     66             Proxy(android.os.IBinder remote) {
     67                 mRemote = remote;
     68             }
     69 
     70             @Override
     71             public android.os.IBinder asBinder() {
     72                 return mRemote;
     73             }
     74 
     75             public java.lang.String getInterfaceDescriptor() {
     76                 return DESCRIPTOR;
     77             }
     78 
     79             @Override
     80             public java.util.List<java.lang.String> getBookList() throws android.os.RemoteException {
     81                 android.os.Parcel _data = android.os.Parcel.obtain();
     82                 android.os.Parcel _reply = android.os.Parcel.obtain();
     83                 java.util.List<java.lang.String> _result;
     84                 try {
     85                     _data.writeInterfaceToken(DESCRIPTOR);
     86                     mRemote.transact(Stub.TRANSACTION_getBookList, _data, _reply, 0);
     87                     _reply.readException();
     88                     _result = _reply.createStringArrayList();
     89                 } finally {
     90                     _reply.recycle();
     91                     _data.recycle();
     92                 }
     93                 return _result;
     94             }
     95 
     96             @Override
     97             public void addBook(java.lang.String book) throws android.os.RemoteException {
     98                 android.os.Parcel _data = android.os.Parcel.obtain();
     99                 android.os.Parcel _reply = android.os.Parcel.obtain();
    100                 try {
    101                     _data.writeInterfaceToken(DESCRIPTOR);
    102                     _data.writeString(book);
    103                     mRemote.transact(Stub.TRANSACTION_addBook, _data, _reply, 0);
    104                     _reply.readException();
    105                 } finally {
    106                     _reply.recycle();
    107                     _data.recycle();
    108                 }
    109             }
    110         }
    111 
    112         static final int TRANSACTION_getBookList = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
    113         static final int TRANSACTION_addBook = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
    114     }
    115 
    116     public java.util.List<java.lang.String> getBookList() throws android.os.RemoteException;
    117 
    118     public void addBook(java.lang.String book) throws android.os.RemoteException;
    119 }

    将该类画成UML图:

    2.完成服务端代码:

     1 public class BookManagerService extends Service {
     2 
     3     private List<String> mBookList = new ArrayList<String>();
     4     private Binder mBinder = new IBookManager.Stub(){
     5 
     6         @Override
     7         public List<String> getBookList() throws RemoteException {
     8             return mBookList;
     9         }
    10 
    11         @Override
    12         public void addBook(String book) throws RemoteException {
    13             mBookList.add(book);
    14         }
    15     };
    16 
    17     public BookManagerService() {
    18     }
    19 
    20     @Override
    21     public void onCreate() {
    22         super.onCreate();
    23         mBookList.add("book1");
    24         mBookList.add("book2");
    25         mBookList.add("book3");
    26     }
    27 
    28     @Override
    29     public IBinder onBind(Intent intent) {
    30         return mBinder;
    31     }
    32 }

    3.客户端代码:

     1 public class MainActivity extends AppCompatActivity implements ServiceConnection{
     2 
     3     private final String TAG = "MAIN";
     4     @Override
     5     protected void onCreate(Bundle savedInstanceState) {
     6         super.onCreate(savedInstanceState);
     7         setContentView(R.layout.activity_main);
     8 
     9         Intent intent = new Intent(this, BookManagerService.class);
    10         bindService(intent, this, BIND_AUTO_CREATE);
    11     }
    12 
    13 
    14     @Override
    15     public void onServiceConnected(ComponentName name, IBinder service) {
    16         //将IBookManaver.Stub对象转换为IBookManager.Stub.Proxy对象
    17         IBookManager bookManager = IBookManager.Stub.asInterface(service);
    18 
    19         try {
    20             //从Service所在的进程返回数据
    21             List<String> list = bookManager.getBookList();
    22             Log.e(TAG, "从Service进程返回的书单:" + list.toString());
    23             bookManager.addBook("book4");
    24             list = bookManager.getBookList();
    25             Log.e(TAG, "添加一本书后返回的书单:" + list.toString());
    26 
    27 
    28         } catch (RemoteException e) {
    29             e.printStackTrace();
    30         }
    31     }
    32 
    33     @Override
    34     public void onServiceDisconnected(ComponentName name) {
    35 
    36     }
    37 }

    4.运行结果:

    1 E/MAIN: 从Service进程返回的书单:[book1, book2, book3]
    2 E/MAIN: 添加一本书后返回的书单:[book1, book2, book3, book4]

    三.原理分析:

    客户端调用BindService(),在onServiceConnected()中获得从服务端Service返回的IBookManager.Stub对象(客户端和服务端各有一个IBookManager.Stub对象),调用IBookManager.Stub.asInterface(service),在不同进程的情况下该方法返回的是IBookManager.Stub.Proxy对象(即IBookManager.Stub的代理类)。然后使用该对象调用bookManager.getBookList()获取服务端提供的服务,从生成的代码中看出该方法调用mRemote.transact(Stub.TRANSACTION_getBookList, _data, _reply, 0)方法,mRemote是IBookManager.Stub对象(由UML图,IBookManager.Stub继承Binder,重写了Binder.onTranscat()),该方法接着调用IBookManager.Stub.onTransect()方法,该方法挂起客户端进程,根据传入的方法代号在服务端的Binder线程池中选择运行指定的服务,这里是自己实现的getBookList()方法。运行结束后结果从mRemote.transact(Stub.TRANSACTION_getBookList, _data, _reply, 0)返回,当前线程继续运行。这样就完成了一次进程间通信。

  • 相关阅读:
    使用Python画ROC曲线以及AUC值
    Machine Learning : Pre-processing features
    资源 | 数十种TensorFlow实现案例汇集:代码+笔记
    在 Mac OS X 终端里使用 Solarized 配色方案
    编译安装GCC 4.7.2
    Office -Word 公式插件Aurora的使用 ——在 Word 中插入 LaTex 公式
    LaTeX 写中文论文而中文显示不出来
    LaTeX 公式编辑之 把符号放在正下方
    Python 判断字符串是否含有指定字符or字符串
    Python 中使用 pandas Dataframe 删除重复的行
  • 原文地址:https://www.cnblogs.com/gatsbydhn/p/5333409.html
Copyright © 2011-2022 走看看