zoukankan      html  css  js  c++  java
  • Android进程间的通信之Messenger

    Android进程间的通信方式可以通过以下两种方式完成:

    1 Android接口定义语言(AIDL)
    2 使用Messenger绑定服务

    本文我们将学习使用Messenger绑定服务的方式进行进程间的通信。

    Android AIDL和Messenger区别

    使用Messenger是执行进程间通信最简单的方法,因为Messenger会在单一线程中创建包含所有请求的队列,这样您就不必对服务进行线程安全设计。而纯粹的AIDL接口会同时向服务发送多个请求,服务随后必须应对多线程处理。AIDL通常应用在服务被设计到单独的应用中的场景(即服务端可客户端不属于同一个app的情况),而Messenger通常应用在同一app的不同进程的场景中。

    Messenger基本思想

    服务端(被动方)提供一个Service来处理客户端(主动方)连接,维护一个Handler(具体来讲:是Handler的子类)来创建Messenger,在onBind时返回Messenger的binder(调用Messenger的getBinder()方法,该方法返回一个IBinder对象,客户端将通过该对象作为参数创建一个Messenger对象用于与服务端进行通信)。

    Messenger使用步骤

    1、服务端实现一个Handler,由其接收来自客户端的每个调用的回调
    2、使用第1步的Handler的实例作为target创建Messenger对象(即该Messenger持有了对Handler的引用)
    3、使用Messenger创建一个IBinder(通过调用Messenger的getBinder()方法),服务端的onBind()方法中将其返回到客户端
    4、客户端使用IBinder将Messenger(引用服务端的Handler实例)实例化,然后使用后者将Message对象发送给服务端
    5、服务端在其Handler中接收每个Message

    这样,客户端并没有调用服务端的“方法”,而客户端传递的消息(Message对象)是服务端在其Handler中接收到的。

    如果想让服务端对客户端发回响应,则还需要在客户端中创建一个持有客户端Handler实现类的Messenger,当客户端收到onServiceConnected()回调时,在向服务发送的Message时,send()方法的replyTo参数中需包含客户端的Messenger。这样,客户端就可在其Handler实现类中接收到来自服务端的响应消息。

    简单示例

    AndroidMainfest.xml

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="yf.exam.client.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <service android:name=".MessengerService" android:process=":custom_process"/>
    </application>

    在上面的配置文件中,service的android:process属性用于在一个单独进程中启动service,看如下图片:

    布局文件很简单,这里只有一个按钮,用于向服务端发送消息并显示服务端响应内容,这里不再给出。

    客户端:MainActivity

     1 public class MainActivity extends Activity {
     2     private static final int REPLY_MSG_ID = 2;
     3     private boolean mServiceConnected = false;
     4     private Button btn = null;
     5     //用于向Service端发送消息的Messenger
     6     private Messenger mBoundServiceMessenger = null;
     7     //用于接收Service发送消息的Messenger
     8     private final Messenger mReceiveMessenger = new Messenger(new ReceiveMessHandler(this));
     9     private ServiceConnection conn = new ServiceConnection() {
    10         @Override
    11         public void onServiceDisconnected(ComponentName name) {
    12             mBoundServiceMessenger = null;
    13             mServiceConnected = false;
    14         }
    15         
    16         @Override
    17         public void onServiceConnected(ComponentName name, IBinder service) {
    18             mBoundServiceMessenger = new Messenger(service);
    19             mServiceConnected = true;
    20         }
    21     };
    22     @Override
    23     protected void onCreate(Bundle savedInstanceState) {
    24         super.onCreate(savedInstanceState);
    25         setContentView(R.layout.activity_main);
    26         btn = (Button)findViewById(R.id.button);
    27         bindService(new Intent(this, MessengerService.class), conn, Context.BIND_AUTO_CREATE);
    28         btn.setOnClickListener(new View.OnClickListener() {
    29             @Override
    30             public void onClick(View v) {
    31                 if(mServiceConnected){
    32                     //获取消息对象
    33                     Message msg = Message.obtain(null, 1, 0, 0);
    34                     try{
    35                         //replyTo参数包含客户端Messenger
    36                         msg.replyTo = mReceiveMessenger;
    37                         //向Service端发送消息
    38                         mBoundServiceMessenger.send(msg);
    39                     }catch(RemoteException re){
    40                         re.printStackTrace();
    41                     }
    42                 }
    43             }
    44         });
    45     }
    46     @Override
    47     protected void onDestroy() {
    48         super.onDestroy();
    49         if(mServiceConnected){
    50             unbindService(conn);
    51             mServiceConnected = false;
    52         }
    53     }
    54     /**
    55      * 客户端实现一个Handler用于接收服务端返回的响应
    56      * @author Administrator
    57      *
    58      */
    59     static class ReceiveMessHandler extends Handler{
    60         //持有当前Activity的弱引用,避免内存泄露
    61         private final WeakReference<MainActivity> mActivity;
    62         public ReceiveMessHandler(MainActivity activity){
    63             mActivity = new WeakReference<MainActivity>(activity);
    64         }
    65         @Override
    66         public void handleMessage(Message msg) {
    67             switch(msg.what){
    68             case REPLY_MSG_ID:
    69                 Toast.makeText(mActivity.get(), msg.getData().getString("msg"), Toast.LENGTH_SHORT).show();
    70                 break;
    71             }
    72         }
    73     }
    74 }

    服务端:MessengerService.java

     1 public class MessengerService extends Service {
     2     private static final int REPLY_MSG_ID = 2;
     3     private static final int MSG_ID = 1;
     4     static class BoundServiceHandler extends Handler{
     5         private final WeakReference<MessengerService> mService;
     6         public BoundServiceHandler(MessengerService service){
     7             mService = new WeakReference<MessengerService>(service);
     8         }
     9         @Override
    10         public void handleMessage(Message msg) {
    11             switch(msg.what){
    12             case MSG_ID:
    13                 Messenger replyMessenger = msg.replyTo;
    14                 Message replyMsg = Message.obtain(null, REPLY_MSG_ID);
    15                 //向客户端响应的消息内容
    16                 Bundle b = new Bundle();
    17                 b.putString("msg", "this is the message reply from service");
    18                 replyMsg.setData(b);
    19                 try{
    20                     replyMessenger.send(replyMsg);
    21                 }catch(RemoteException re){
    22                     re.printStackTrace();
    23                 }
    24                 break;
    25                 default:
    26                     super.handleMessage(msg);
    27             }
    28         }
    29     }
    30     private final Messenger mMessenger = new Messenger(new BoundServiceHandler(this));
    31     @Override
    32     public IBinder onBind(Intent intent) {
    33         Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show();
    34         return mMessenger.getBinder();
    35     }
    36 }

    此外,上述例子中所有的Handler的实现类都被声明为static并使用Service或Activity的WeakReference。如果不这样做,编译器会给出警告信息“This handler class should be static or leaks might occur”。通过使用弱引用的方式,就允许Service或Activity进行垃圾收集了。

  • 相关阅读:
    Mysql mysql lost connection to server during query 问题解决方法
    【转】程序员必须知道的几个Git代码托管平台
    FIFO存储器
    JUCE_FIFO实现分析
    【转】HashMap实现原理分析
    【转】int && 非常量右值
    【API】注册表编程基础-RegCreateKeyEx、RegSetValueEx
    【API】文件操作编程基础-CreateFile、WriteFile、SetFilePointer
    【逆向知识】裸函数(Naked函数)
    【逆向知识】堆栈图-汇编中的函数
  • 原文地址:https://www.cnblogs.com/e007/p/6106482.html
Copyright © 2011-2022 走看看