zoukankan      html  css  js  c++  java
  • Android 基于Message的进程间通信 Messenger完全解析

    1、概述

    Binder能干什么?Binder可以提供系统中任何程序都可以访问的全局服务。这个功能当然是任何系统都应该提供的,下面我们简单看一下Android的Binder的框架

    Android Binder框架分为服务器接口、Binder驱动、以及客户端接口;简单想一下,需要提供一个全局服务,那么全局服务那端即是服务器接口,任何程序即客户端接口,它们之间通过一个Binder驱动访问。

    服务器端接口:实际上是Binder类的对象,该对象一旦创建,内部则会启动一个隐藏线程,会接收Binder驱动发送的消息,收到消息后,会执行Binder对象中的onTransact()函数,并按照该函数的参数执行不同的服务器端代码。

    Binder驱动:该对象也为Binder类的实例,客户端通过该对象访问远程服务。

    客户端接口:获得Binder驱动,调用其transact()发送消息至服务器

    如果大家对上述不了解,没关系,下面会通过例子来更好的说明,实践是检验真理的唯一标准嘛

    2、AIDL的使用

    如果对Android比较熟悉,那么一定使用过AIDL,如果你还不了解,那么也没关系,下面会使用一个例子展示AIDL的用法。

    我们使用AIDL实现一个跨进程的加减法调用

    1、服务端

    新建一个项目,创建一个包名:com.zhy.calc.aidl,在包内创建一个ICalcAIDL文件:

    1. package com.zhy.calc.aidl;  
    2. interface ICalcAIDL  
    3. {  
    4.     int add(int x , int y);  
    5.     int min(int x , int y );  
    6. }  


    注意,文件名为ICalcAIDL.aidl

    然后在项目的gen目录下会生成一个ICalcAIDL.Java文件,暂时不贴这个文件的代码了,后面会详细说明

    然后我们在项目中新建一个Service,代码如下:

    1. package com.example.zhy_binder;  
    2.   
    3. import com.zhy.calc.aidl.ICalcAIDL;  
    4.   
    5. import android.app.Service;  
    6. import android.content.Intent;  
    7. import android.os.IBinder;  
    8. import android.os.RemoteException;  
    9. import android.util.Log;  
    10.   
    11. public class CalcService extends Service  
    12. {  
    13.     private static final String TAG = "server";  
    14.   
    15.     public void onCreate()  
    16.     {  
    17.         Log.e(TAG, "onCreate");  
    18.     }  
    19.   
    20.     public IBinder onBind(Intent t)  
    21.     {  
    22.         Log.e(TAG, "onBind");  
    23.         return mBinder;  
    24.     }  
    25.   
    26.     public void onDestroy()  
    27.     {  
    28.         Log.e(TAG, "onDestroy");  
    29.         super.onDestroy();  
    30.     }  
    31.   
    32.     public boolean onUnbind(Intent intent)  
    33.     {  
    34.         Log.e(TAG, "onUnbind");  
    35.         return super.onUnbind(intent);  
    36.     }  
    37.   
    38.     public void onRebind(Intent intent)  
    39.     {  
    40.         Log.e(TAG, "onRebind");  
    41.         super.onRebind(intent);  
    42.     }  
    43.   
    44.     private final ICalcAIDL.Stub mBinder = new ICalcAIDL.Stub()  
    45.     {  
    46.   
    47.         @Override  
    48.         public int add(int x, int y) throws RemoteException  
    49.         {  
    50.             return x + y;  
    51.         }  
    52.   
    53.         @Override  
    54.         public int min(int x, int y) throws RemoteException  
    55.         {  
    56.             return x - y;  
    57.         }  
    58.   
    59.     };  
    60.   
    61. }  

    在此Service中,使用生成的ICalcAIDL创建了一个mBinder的对象,并在Service的onBind方法中返回

    最后记得在AndroidManifest中注册

    1. <service android:name="com.example.zhy_binder.CalcService" >  
    2.            <intent-filter>  
    3.                <action android:name="com.zhy.aidl.calc" />  
    4.   
    5.                <category android:name="android.intent.category.DEFAULT" />  
    6.            </intent-filter>  
    7.        </service>  


    这里我们指定了一个name,因为我们一会会在别的应用程序中通过Intent来查找此Service;这个不需要Activity,所以我也就没写Activity,安装完成也看不到安装图标,悄悄在后台运行着。

    到此,服务端编写完毕。下面开始编写客户端

    2、客户端

    客户端的代码比较简单,创建一个布局,里面包含4个按钮,分别为绑定服务,解除绑定,调用加法,调用减法

    布局文件:

    1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    2.     xmlns:tools="http://schemas.android.com/tools"  
    3.     android:layout_width="match_parent"  
    4.     android:layout_height="match_parent"  
    5.     android:orientation="vertical" >  
    6.   
    7.     <Button  
    8.         android:layout_width="fill_parent"  
    9.         android:layout_height="wrap_content"  
    10.         android:onClick="bindService"  
    11.         android:text="BindService" />  
    12.   
    13.     <Button  
    14.         android:layout_width="fill_parent"  
    15.         android:layout_height="wrap_content"  
    16.         android:onClick="unbindService"  
    17.         android:text="UnbindService" />  
    18.   
    19.     <Button  
    20.         android:layout_width="fill_parent"  
    21.         android:layout_height="wrap_content"  
    22.         android:onClick="addInvoked"  
    23.         android:text="12+12" />  
    24.   
    25.     <Button  
    26.         android:layout_width="fill_parent"  
    27.         android:layout_height="wrap_content"  
    28.         android:onClick="minInvoked"  
    29.         android:text="50-12" />  
    30.   
    31. </LinearLayout>  


    主Activity

    1. package com.example.zhy_binder_client;  
    2.   
    3. import android.app.Activity;  
    4. import android.content.ComponentName;  
    5. import android.content.Context;  
    6. import android.content.Intent;  
    7. import android.content.ServiceConnection;  
    8. import android.os.Bundle;  
    9. import android.os.IBinder;  
    10. import android.util.Log;  
    11. import android.view.View;  
    12. import android.widget.Toast;  
    13.   
    14. import com.zhy.calc.aidl.ICalcAIDL;  
    15.   
    16. public class MainActivity extends Activity  
    17. {  
    18.     private ICalcAIDL mCalcAidl;  
    19.   
    20.     private ServiceConnection mServiceConn = new ServiceConnection()  
    21.     {  
    22.         @Override  
    23.         public void onServiceDisconnected(ComponentName name)  
    24.         {  
    25.             Log.e("client", "onServiceDisconnected");  
    26.             mCalcAidl = null;  
    27.         }  
    28.   
    29.         @Override  
    30.         public void onServiceConnected(ComponentName name, IBinder service)  
    31.         {  
    32.             Log.e("client", "onServiceConnected");  
    33.             mCalcAidl = ICalcAIDL.Stub.asInterface(service);  
    34.         }  
    35.     };  
    36.   
    37.     @Override  
    38.     protected void onCreate(Bundle savedInstanceState)  
    39.     {  
    40.         super.onCreate(savedInstanceState);  
    41.         setContentView(R.layout.activity_main);  
    42.   
    43.     }  
    44.       
    45.     /** 
    46.      * 点击BindService按钮时调用 
    47.      * @param view 
    48.      */  
    49.     public void bindService(View view)  
    50.     {  
    51.         Intent intent = new Intent();  
    52.         intent.setAction("com.zhy.aidl.calc");  
    53.         bindService(intent, mServiceConn, Context.BIND_AUTO_CREATE);  
    54.     }  
    55.     /** 
    56.      * 点击unBindService按钮时调用 
    57.      * @param view 
    58.      */  
    59.     public void unbindService(View view)  
    60.     {  
    61.         unbindService(mServiceConn);  
    62.     }  
    63.     /** 
    64.      * 点击12+12按钮时调用 
    65.      * @param view 
    66.      */  
    67.     public void addInvoked(View view) throws Exception  
    68.     {  
    69.   
    70.         if (mCalcAidl != null)  
    71.         {  
    72.             int addRes = mCalcAidl.add(12, 12);  
    73.             Toast.makeText(this, addRes + "", Toast.LENGTH_SHORT).show();  
    74.         } else  
    75.         {  
    76.             Toast.makeText(this, "服务器被异常杀死,请重新绑定服务端", Toast.LENGTH_SHORT)  
    77.                     .show();  
    78.   
    79.         }  
    80.   
    81.     }  
    82.     /** 
    83.      * 点击50-12按钮时调用 
    84.      * @param view 
    85.      */  
    86.     public void minInvoked(View view) throws Exception  
    87.     {  
    88.   
    89.         if (mCalcAidl != null)  
    90.         {  
    91.             int addRes = mCalcAidl.min(58, 12);  
    92.             Toast.makeText(this, addRes + "", Toast.LENGTH_SHORT).show();  
    93.         } else  
    94.         {  
    95.             Toast.makeText(this, "服务端未绑定或被异常杀死,请重新绑定服务端", Toast.LENGTH_SHORT)  
    96.                     .show();  
    97.   
    98.         }  
    99.   
    100.     }  
    101.   
    102. }  

    很标准的绑定服务的代码。

    直接看运行结果:

    我们首先点击BindService按钮,查看log

    1. 08-09 22:56:38.959: E/server(29692): onCreate  
    2. 08-09 22:56:38.959: E/server(29692): onBind  
    3. 08-09 22:56:38.959: E/client(29477): onServiceConnected  

    可以看到,点击BindService之后,服务端执行了onCreate和onBind的方法,并且客户端执行了onServiceConnected方法,标明服务器与客户端已经联通

    然后点击12+12,50-12可以成功的调用服务端的代码并返回正确的结果

    下面我们再点击unBindService

    1. 08-09 22:59:25.567: E/server(29692): onUnbind  
    2. 08-09 22:59:25.567: E/server(29692): onDestroy  

    由于我们当前只有一个客户端绑定了此Service,所以Service调用了onUnbind和onDestory

    然后我们继续点击12+12,50-12,通过上图可以看到,依然可以正确执行,也就是说即使onUnbind被调用,连接也是不会断开的,那么什么时候会端口呢?

    即当服务端被异常终止的时候,比如我们现在在手机的正在执行的程序中找到该服务:

    点击停止,此时查看log

    1. 08-09 23:04:21.433: E/client(30146): onServiceDisconnected  

    可以看到调用了onServiceDisconnected方法,此时连接被断开,现在点击12+12,50-12的按钮,则会弹出Toast服务端断开的提示。

    说了这么多,似乎和Binder框架没什么关系,下面我们来具体看一看AIDL为什么做了些什么。

    3、分析AIDL生成的代码

     

    1、服务端

    先看服务端的代码,可以看到我们服务端提供的服务是由

    1. private final ICalcAIDL.Stub mBinder = new ICalcAIDL.Stub()  
    2.     {  
    3.   
    4.         @Override  
    5.         public int add(int x, int y) throws RemoteException  
    6.         {  
    7.             return x + y;  
    8.         }  
    9.   
    10.         @Override  
    11.         public int min(int x, int y) throws RemoteException  
    12.         {  
    13.             return x - y;  
    14.         }  
    15.   
    16.     };  


    ICalcAILD.Stub来执行的,让我们来看看Stub这个类的声明:

    1. public static abstract class Stub extends android.os.Binder implements com.zhy.calc.aidl.ICalcAIDL  


    清楚的看到这个类是Binder的子类,是不是符合我们文章开通所说的服务端其实是一个Binder类的实例

    接下来看它的onTransact()方法:

    1. @Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException  
    2. {  
    3. switch (code)  
    4. {  
    5. case INTERFACE_TRANSACTION:  
    6. {  
    7. reply.writeString(DESCRIPTOR);  
    8. return true;  
    9. }  
    10. case TRANSACTION_add:  
    11. {  
    12. data.enforceInterface(DESCRIPTOR);  
    13. int _arg0;  
    14. _arg0 = data.readInt();  
    15. int _arg1;  
    16. _arg1 = data.readInt();  
    17. int _result = this.add(_arg0, _arg1);  
    18. reply.writeNoException();  
    19. reply.writeInt(_result);  
    20. return true;  
    21. }  
    22. case TRANSACTION_min:  
    23. {  
    24. data.enforceInterface(DESCRIPTOR);  
    25. int _arg0;  
    26. _arg0 = data.readInt();  
    27. int _arg1;  
    28. _arg1 = data.readInt();  
    29. int _result = this.min(_arg0, _arg1);  
    30. reply.writeNoException();  
    31. reply.writeInt(_result);  
    32. return true;  
    33. }  
    34. }  
    35. return super.onTransact(code, data, reply, flags);  
    36. }  


    文章开头也说到服务端的Binder实例会根据客户端依靠Binder驱动发来的消息,执行onTransact方法,然后由其参数决定执行服务端的代码。

    可以看到onTransact有四个参数

    code , data ,replay , flags

    code 是一个整形的唯一标识,用于区分执行哪个方法,客户端会传递此参数,告诉服务端执行哪个方法

    data客户端传递过来的参数

    replay服务器返回回去的值

    flags标明是否有返回值,0为有(双向),1为没有(单向)

    我们仔细看case TRANSACTION_min中的代码

    data.enforceInterface(DESCRIPTOR);与客户端的writeInterfaceToken对用,标识远程服务的名称

    int _arg0;
    _arg0 = data.readInt();
    int _arg1;
    _arg1 = data.readInt();

    接下来分别读取了客户端传入的两个参数

    int _result = this.min(_arg0, _arg1);
    reply.writeNoException();
    reply.writeInt(_result);

    然后执行this.min,即我们实现的min方法;返回result由reply写回。

    add同理,可以看到服务端通过AIDL生成Stub的类,封装了服务端本来需要写的代码。

    2、客户端

    客户端主要通过ServiceConnected与服务端连接

    1. private ServiceConnection mServiceConn = new ServiceConnection()  
    2.     {  
    3.         @Override  
    4.         public void onServiceDisconnected(ComponentName name)  
    5.         {  
    6.             Log.e("client", "onServiceDisconnected");  
    7.             mCalcAidl = null;  
    8.         }  
    9.   
    10.         @Override  
    11.         public void onServiceConnected(ComponentName name, IBinder service)  
    12.         {  
    13.             Log.e("client", "onServiceConnected");  
    14.             mCalcAidl = ICalcAIDL.Stub.asInterface(service);  
    15.         }  
    16.     };  


    如果你比较敏锐,应该会猜到这个onServiceConnected中的IBinder实例,其实就是我们文章开通所说的Binder驱动,也是一个Binder实例

    在ICalcAIDL.Stub.asInterface中最终调用了:

    1. return new com.zhy.calc.aidl.ICalcAIDL.Stub.Proxy(obj);  


    这个Proxy实例传入了我们的Binder驱动,并且封装了我们调用服务端的代码,文章开头说,客户端会通过Binder驱动的transact()方法调用服务端代码

    直接看Proxy中的add方法

    1. @Override public int add(int x, int y) throws android.os.RemoteException  
    2. {  
    3. android.os.Parcel _data = android.os.Parcel.obtain();  
    4. android.os.Parcel _reply = android.os.Parcel.obtain();  
    5. int _result;  
    6. try {  
    7. _data.writeInterfaceToken(DESCRIPTOR);  
    8. _data.writeInt(x);  
    9. _data.writeInt(y);  
    10. mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);  
    11. _reply.readException();  
    12. _result = _reply.readInt();  
    13. }  
    14. finally {  
    15. _reply.recycle();  
    16. _data.recycle();  
    17. }  
    18. return _result;  
    19. }  


    首先声明两个Parcel对象,一个用于传递数据,一个用户接收返回的数据

    _data.writeInterfaceToken(DESCRIPTOR);与服务器端的enforceInterfac对应

    _data.writeInt(x);
    _data.writeInt(y);写入需要传递的参数

    mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);

    终于看到了我们的transact方法,第一个对应服务端的code,_data,_repay分别对应服务端的data,reply,0表示是双向的

    _reply.readException();
    _result = _reply.readInt();

    最后读出我们服务端返回的数据,然后return。可以看到和服务端的onTransact基本是一行一行对应的。

    到此,我们已经通过AIDL生成的代码解释了Android Binder框架的工作原理。Service的作用其实就是为我们创建Binder驱动,即服务端与客户端连接的桥梁。

    AIDL其实通过我们写的aidl文件,帮助我们生成了一个接口,一个Stub类用于服务端,一个Proxy类用于客户端调用。那么我们是否可以不通过写AIDL来实现远程的通信呢?下面向大家展示如何完全不依赖AIDL来实现客户端与服务端的通信。

    4、不依赖AIDL实现程序间通讯

     

    1、服务端代码

    我们新建一个CalcPlusService.java用于实现两个数的乘和除

    1. package com.example.zhy_binder;  
    2.   
    3. import android.app.Service;  
    4. import android.content.Intent;  
    5. import android.os.Binder;  
    6. import android.os.IBinder;  
    7. import android.os.Parcel;  
    8. import android.os.RemoteException;  
    9. import android.util.Log;  
    10.   
    11. public class CalcPlusService extends Service  
    12. {  
    13.     private static final String DESCRIPTOR = "CalcPlusService";  
    14.     private static final String TAG = "CalcPlusService";  
    15.   
    16.     public void onCreate()  
    17.     {  
    18.         Log.e(TAG, "onCreate");  
    19.     }  
    20.   
    21.     @Override  
    22.     public int onStartCommand(Intent intent, int flags, int startId)  
    23.     {  
    24.         Log.e(TAG, "onStartCommand");  
    25.         return super.onStartCommand(intent, flags, startId);  
    26.     }  
    27.   
    28.     public IBinder onBind(Intent t)  
    29.     {  
    30.         Log.e(TAG, "onBind");  
    31.         return mBinder;  
    32.     }  
    33.   
    34.     public void onDestroy()  
    35.     {  
    36.         Log.e(TAG, "onDestroy");  
    37.         super.onDestroy();  
    38.     }  
    39.   
    40.     public boolean onUnbind(Intent intent)  
    41.     {  
    42.         Log.e(TAG, "onUnbind");  
    43.         return super.onUnbind(intent);  
    44.     }  
    45.   
    46.     public void onRebind(Intent intent)  
    47.     {  
    48.         Log.e(TAG, "onRebind");  
    49.         super.onRebind(intent);  
    50.     }  
    51.   
    52.     private MyBinder mBinder = new MyBinder();  
    53.   
    54.     private class MyBinder extends Binder  
    55.     {  
    56.         @Override  
    57.         protected boolean onTransact(int code, Parcel data, Parcel reply,  
    58.                 int flags) throws RemoteException  
    59.         {  
    60.             switch (code)  
    61.             {  
    62.             case 0x110:  
    63.             {  
    64.                 data.enforceInterface(DESCRIPTOR);  
    65.                 int _arg0;  
    66.                 _arg0 = data.readInt();  
    67.                 int _arg1;  
    68.                 _arg1 = data.readInt();  
    69.                 int _result = _arg0 * _arg1;  
    70.                 reply.writeNoException();  
    71.                 reply.writeInt(_result);  
    72.                 return true;  
    73.             }  
    74.             case 0x111:  
    75.             {  
    76.                 data.enforceInterface(DESCRIPTOR);  
    77.                 int _arg0;  
    78.                 _arg0 = data.readInt();  
    79.                 int _arg1;  
    80.                 _arg1 = data.readInt();  
    81.                 int _result = _arg0 / _arg1;  
    82.                 reply.writeNoException();  
    83.                 reply.writeInt(_result);  
    84.                 return true;  
    85.             }  
    86.             }  
    87.             return super.onTransact(code, data, reply, flags);  
    88.         }  
    89.   
    90.     };  
    91.   
    92. }  


    我们自己实现服务端,所以我们自定义了一个Binder子类,然后复写了其onTransact方法,我们指定服务的标识为CalcPlusService,然后0x110为乘,0x111为除;

    记得在AndroidMenifest中注册

    1. <service android:name="com.example.zhy_binder.CalcPlusService" >  
    2.            <intent-filter>  
    3.                <action android:name="com.zhy.aidl.calcplus" />  
    4.                <category android:name="android.intent.category.DEFAULT" />  
    5.            </intent-filter>  
    6.        </service>  


    服务端代码结束。

    2、客户端代码

    单独新建了一个项目,代码和上例很类似

    首先布局文件:

    1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    2.     xmlns:tools="http://schemas.android.com/tools"  
    3.     android:layout_width="match_parent"  
    4.     android:layout_height="match_parent"  
    5.     android:orientation="vertical" >  
    6.   
    7.     <Button  
    8.         android:layout_width="fill_parent"  
    9.         android:layout_height="wrap_content"  
    10.         android:onClick="bindService"  
    11.         android:text="BindService" />  
    12.   
    13.     <Button  
    14.         android:layout_width="fill_parent"  
    15.         android:layout_height="wrap_content"  
    16.         android:onClick="unbindService"  
    17.         android:text="UnbindService" />  
    18.   
    19.     <Button  
    20.         android:layout_width="fill_parent"  
    21.         android:layout_height="wrap_content"  
    22.         android:onClick="mulInvoked"  
    23.         android:text="50*12" />  
    24.       
    25.     <Button  
    26.         android:layout_width="fill_parent"  
    27.         android:layout_height="wrap_content"  
    28.         android:onClick="divInvoked"  
    29.         android:text="36/12" />  
    30.   
    31. </LinearLayout>  


    可以看到加入了乘和除

    然后是Activity的代码

    1. package com.example.zhy_binder_client03;  
    2.   
    3. import android.app.Activity;  
    4. import android.content.ComponentName;  
    5. import android.content.Context;  
    6. import android.content.Intent;  
    7. import android.content.ServiceConnection;  
    8. import android.os.Bundle;  
    9. import android.os.IBinder;  
    10. import android.os.RemoteException;  
    11. import android.util.Log;  
    12. import android.view.View;  
    13. import android.widget.Toast;  
    14.   
    15. public class MainActivity extends Activity  
    16. {  
    17.   
    18.     private IBinder mPlusBinder;  
    19.     private ServiceConnection mServiceConnPlus = new ServiceConnection()  
    20.     {  
    21.         @Override  
    22.         public void onServiceDisconnected(ComponentName name)  
    23.         {  
    24.             Log.e("client", "mServiceConnPlus onServiceDisconnected");  
    25.         }  
    26.   
    27.         @Override  
    28.         public void onServiceConnected(ComponentName name, IBinder service)  
    29.         {  
    30.   
    31.             Log.e("client", " mServiceConnPlus onServiceConnected");  
    32.             mPlusBinder = service;  
    33.         }  
    34.     };  
    35.   
    36.     @Override  
    37.     protected void onCreate(Bundle savedInstanceState)  
    38.     {  
    39.         super.onCreate(savedInstanceState);  
    40.         setContentView(R.layout.activity_main);  
    41.   
    42.     }  
    43.   
    44.     public void bindService(View view)  
    45.     {  
    46.         Intent intentPlus = new Intent();  
    47.         intentPlus.setAction("com.zhy.aidl.calcplus");  
    48.         boolean plus = bindService(intentPlus, mServiceConnPlus,  
    49.                 Context.BIND_AUTO_CREATE);  
    50.         Log.e("plus", plus + "");  
    51.     }  
    52.   
    53.     public void unbindService(View view)  
    54.     {  
    55.         unbindService(mServiceConnPlus);  
    56.     }  
    57.   
    58.     public void mulInvoked(View view)  
    59.     {  
    60.   
    61.         if (mPlusBinder == null)  
    62.         {  
    63.             Toast.makeText(this, "未连接服务端或服务端被异常杀死", Toast.LENGTH_SHORT).show();  
    64.         } else  
    65.         {  
    66.             android.os.Parcel _data = android.os.Parcel.obtain();  
    67.             android.os.Parcel _reply = android.os.Parcel.obtain();  
    68.             int _result;  
    69.             try  
    70.             {  
    71.                 _data.writeInterfaceToken("CalcPlusService");  
    72.                 _data.writeInt(50);  
    73.                 _data.writeInt(12);  
    74.                 mPlusBinder.transact(0x110, _data, _reply, 0);  
    75.                 _reply.readException();  
    76.                 _result = _reply.readInt();  
    77.                 Toast.makeText(this, _result + "", Toast.LENGTH_SHORT).show();  
    78.   
    79.             } catch (RemoteException e)  
    80.             {  
    81.                 e.printStackTrace();  
    82.             } finally  
    83.             {  
    84.                 _reply.recycle();  
    85.                 _data.recycle();  
    86.             }  
    87.         }  
    88.   
    89.     }  
    90.       
    91.     public void divInvoked(View view)  
    92.     {  
    93.   
    94.         if (mPlusBinder == null)  
    95.         {  
    96.             Toast.makeText(this, "未连接服务端或服务端被异常杀死", Toast.LENGTH_SHORT).show();  
    97.         } else  
    98.         {  
    99.             android.os.Parcel _data = android.os.Parcel.obtain();  
    100.             android.os.Parcel _reply = android.os.Parcel.obtain();  
    101.             int _result;  
    102.             try  
    103.             {  
    104.                 _data.writeInterfaceToken("CalcPlusService");  
    105.                 _data.writeInt(36);  
    106.                 _data.writeInt(12);  
    107.                 mPlusBinder.transact(0x111, _data, _reply, 0);  
    108.                 _reply.readException();  
    109.                 _result = _reply.readInt();  
    110.                 Toast.makeText(this, _result + "", Toast.LENGTH_SHORT).show();  
    111.   
    112.             } catch (RemoteException e)  
    113.             {  
    114.                 e.printStackTrace();  
    115.             } finally  
    116.             {  
    117.                 _reply.recycle();  
    118.                 _data.recycle();  
    119.             }  
    120.         }  
    121.   
    122.     }  
    123. }  


    为了明了,我直接在mulInvoked里面写了代码,和服务端都没有抽象出一个接口。首先绑定服务时,通过onServiceConnected得到Binder驱动即mPlusBinder;

    然后准备数据,调用transact方法,通过code指定执行服务端哪个方法,代码和上面的分析一致。

    下面看运行结果:

    是不是很好的实现了我们两个应用程序间的通讯,并没有使用aidl文件,也从侧面分析了我们上述分析是正确的。

    好了,就到这里,相信大家看完这篇博文,对aidl和Binder的理解也会更加深刻。

    测试代码点击下载

    代码先安装server端的代码,然后再安装client端的。。。

     

  • 相关阅读:
    <%%>,<%!%>,<%=%>,<%@%>,<jsp:include><%@ include%>区别
    struts2学习
    struts2标签
    OGNL
    Andriod XML Editor cannot process this input
    Error 错误: 找不到或无法加载主类
    Class<T> 与T区别
    poi
    POI-java读取Excel(包含合并单元格)
    SQL-字符串连接聚合函数
  • 原文地址:https://www.cnblogs.com/ldq2016/p/7307015.html
Copyright © 2011-2022 走看看