Android 进程间通信的几种实现方式

一、概述

       由于应用程序之间不能共享内存。在不同应用程序之间交互数据(跨进程通讯),在android SDK中提供了4种用于跨进程通讯的方式。这4种方式正好对应于android系统中4种应用程序组件:Activity、Content Provider、Broadcast和Service。其中Activity可以跨进程调用其他应用程序的Activity;Content Provider可以跨进程访问其他应用程序中的数据(以Cursor对象形式返回),当然,也可以对其他应用程序的数据进行增、删、改操 作;Broadcast可以向android系统中所有应用程序发送广播,而需要跨进程通讯的应用程序可以监听这些广播;Service和Content Provider类似,也可以访问其他应用程序中的数据,但不同的是,Content Provider返回的是Cursor对象,而Service返回的是Java对象,这种可以跨进程通讯的服务叫AIDL服务。



 Activity

  Activity的跨进程访问与进程内访问略有不同。虽然它们都需要Intent对象,但跨进程访问并不需要指定Context对象和Activity的 Class对象,而需要指定的是要访问的Activity所对应的Action(一个字符串)。有些Activity还需要指定一个Uri(通过 Intent构造方法的第2个参数指定)。

       在android系统中有很多应用程序提供了可以跨进程访问的Activity,例如,下面的代码可以直接调用拨打电话的Activity。

  1. Intent callIntent = new  Intent(Intent.ACTION_CALL, Uri.parse("tel:12345678" );  
  2. startActivity(callIntent);



Content Provider 

      Android应用程序可以使用文件或SqlLite数据库来存储数据。Content Provider提供了一种在多个应用程序之间数据共享的方式(跨进程共享数据)。应用程序可以利用Content Provider完成下面的工作

1. 查询数据
2. 修改数据
3. 添加数据
4. 删除数据

        虽然Content Provider也可以在同一个应用程序中被访问,但这么做并没有什么意义。Content Provider存在的目的向其他应用程序共享数据和允许其他应用程序对数据进行增、删、改操作。
Android系统本身提供了很多Content Provider,例如,音频、视频、联系人信息等等。我们可以通过这些Content Provider获得相关信息的列表。这些列表数据将以Cursor对象返回。因此,从Content Provider返回的数据是二维表的形式。


广播(Broadcast) 
      广播是一种被动跨进程通讯的方式。当某个程序向系统发送广播时,其他的应用程序只能被动地接收广播数据。这就象电台进行广播一样,听众只能被动地收听,而不能主动与电台进行沟通。
在应用程序中发送广播比较简单。只需要调用sendBroadcast方法即可。该方法需要一个Intent对象。通过Intent对象可以发送需要广播的数据。



Service

1.利用AIDL Service实现跨进程通信

        这是我个人比较推崇的方式,因为它相比Broadcast而言,虽然实现上稍微麻烦了一点,但是它的优势就是不会像广播那样在手机中的广播较多时会有明显的时延,甚至有广播发送不成功的情况出现。 

       注意普通的Service并不能实现跨进程操作,实际上普通的Service和它所在的应用处于同一个进程中,而且它也不会专门开一条新的线程,因此如果在普通的Service中实现在耗时的任务,需要新开线程。

       要实现跨进程通信,需要借助AIDL(Android Interface Definition Language)。Android中的跨进程服务其实是采用C/S的架构,因而AIDL的目的就是实现通信接口。

      首先举一个简单的栗子。

      服务端代码如下:

      首先是aidl的代码:

[java]  view plain  copy
  1. package com.android.service;  
  2.   
  3. interface IData  
  4. {  
  5.     int getRoomNum();  
  6. }  

RoomService的代码如下:

[java]  view plain  copy
  1. package com.android.service;  
  2.   
  3. import android.app.Service;  
  4. import android.content.Intent;  
  5. import android.os.IBinder;  
  6. import android.os.RemoteException;  
  7.   
  8. public class RoomService extends Service{  
  9.   
  10.     private IData.Stub mBinder=new IData.Stub() {  
  11.           
  12.         @Override  
  13.         public int getRoomNum() throws RemoteException {  
  14.              return 3008;  
  15.         }  
  16.     };  
  17.   
  18.     @Override  
  19.     public IBinder onBind(Intent intent) {  
  20.         return mBinder;  
  21.     }  
  22.   
  23. }  
AndroidManifest如下:

[html]  view plain  copy
  1. <span id="19_nwp" style="padding: 0px; width: auto; height: auto; float: none;"><a target=_blank id="19_nwl" href="http://cpro.baidu.com/cpro/ui/uijs.php?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=20&is_app=0&jk=e1c94d8eb3072940&k=xml&k0=xml&kdi0=0&luki=8&mcpm=0&n=10&p=baidu&q=65035100_cpr&rb=0&rs=1&seller_id=1&sid=402907b38e4dc9e1&ssp2=1&stid=9&t=tpclicked3_hc&td=1836545&tu=u1836545&u=http%3A%2F%2Fwww%2Ebubuko%2Ecom%2Finfodetail%2D458771%2Ehtml&urlid=0" target="_blank" mpid="19" style="padding: 0px; color: rgb(51, 51, 51); text-decoration: none;"><span style="padding: 0px; color: rgb(0, 0, 255); width: auto; height: auto;">xmlspan>a>span> version="1.0" encoding="utf-8"?>  
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     package="com.android.aidlsampleservice"  
  4.     android:versionCode="1"  
  5.     android:versionName="1.0" >  
  6.   
  7.     <uses-sdk  
  8.         android:minSdkVersion="8"  
  9.         android:targetSdkVersion="17" />  
  10.   
  11.     <application  
  12.         android:allowBackup="true"  
  13.         android:icon="@drawable/ic_launcher"  
  14.         android:label="@string/app_name"  
  15.         android:theme="@<span id="20_nwp" style="padding: 0px; width: auto; height: auto; float: none;"><a target=_blank id="20_nwl" href="http://cpro.baidu.com/cpro/ui/uijs.php?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=20&is_app=0&jk=e1c94d8eb3072940&k=style&k0=style&kdi0=0&luki=5&mcpm=0&n=10&p=baidu&q=65035100_cpr&rb=0&rs=1&seller_id=1&sid=402907b38e4dc9e1&ssp2=1&stid=9&t=tpclicked3_hc&td=1836545&tu=u1836545&u=http%3A%2F%2Fwww%2Ebubuko%2Ecom%2Finfodetail%2D458771%2Ehtml&urlid=0" target="_blank" mpid="20" style="padding: 0px; color: rgb(51, 51, 51); text-decoration: none;"><span style="padding: 0px; color: rgb(0, 0, 255); width: auto; height: auto;">stylespan>a>span>/AppTheme" >        
  16.         <service android:name="com.android.service.RoomService">  
  17.             <intent-filter>  
  18.                 <action android:name="com.aidl.service.room"/>  
  19.             intent-filter>  
  20.         service>  
  21.     application>  
  22.   
  23. manifest>  
然后运行该Service所在的Project即可。

客户端代码如下:

注意客户端也要有aidl文件,所以最简单的办法就是将Service端中aidl所在的包直接复制过去。另外要注意的是在onDestroy中要解除和Service的绑定。

MainActivity.java的代码如下:

[java]  view plain  copy
  1. package com.example.aidlsampleclient;  
  2.   
  3. import com.android.service.IData;  
  4.   
  5. import android.os.Bundle;  
  6. import android.os.IBinder;  
  7. import android.os.RemoteException;  
  8. import android.app.Activity;  
  9. import android.content.ComponentName;  
  10. import android.content.Intent;  
  11. import android.content.ServiceConnection;  
  12. import android.util.Log;  
  13. import android.view.Menu;  
  14. import android.widget.Button;  
  15. import android.widget.Toast;  
  16. import android.view.View;  
  17.   
  18. public class MainActivity extends Activity implements View.OnClickListener{  
  19.   
  20.       
  21.     private static final String TAG="MainActivity";  
  22.     private static final String ROOM_SERVICE_ACTION="com.aidl.service.room";  
  23.       
  24.     private Button bindServiceButton;  
  25.     private Button getServiceButton;  
  26.       
  27.       
  28.     IData mData;  
  29.       
  30.     private ServiceConnection conn=new ServiceConnection()  
  31.     {  
  32.   
  33.         @Override  
  34.         public void onServiceConnected(ComponentName name, IBinder service) {  
  35.           
  36.             Log.i(TAG,"----------------onServiceConnected--------");  
  37.             mData=IData.Stub.asInterface(service);  
  38.         }  
  39.   
  40.         @Override  
  41.         public void onServiceDisconnected(ComponentName name) {  
  42.           
  43.             Log.i(TAG,"----------------onServiceDisconnected-------------");  
  44.             mData=null;  
  45.               
  46.         }  
  47.           
  48.     };  
  49.       
  50.     private void initView()  
  51.     {  
  52.         bindServiceButton=(Button)findViewById(R.id.bindServiceButton);  
  53.         getServiceButton=(Button)findViewById(R.id.getServiceButton);  
  54.         bindServiceButton.setOnClickListener(this);  
  55.         getServiceButton.setOnClickListener(this);  
  56.     }  
  57.     @Override  
  58.     protected void onCreate(Bundle savedInstanceState) {  
  59.         super.onCreate(savedInstanceState);  
  60.         setContentView(R.layout.activity_main);  
  61.         initView();  
  62.     }  
  63.       
  64.     @Override  
  65.     public void onClick(View v) {  
  66.         // TODO Auto-generated method stub  
  67.         "17_nwp" style="padding: 0px; width: auto; height: auto; float: none;">"17_nwl" href="http://cpro.baidu.com/cpro/ui/uijs.php?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=20&is_app=0&jk=e1c94d8eb3072940&k=switch&k0=switch&kdi0=0&luki=10&mcpm=0&n=10&p=baidu&q=65035100_cpr&rb=0&rs=1&seller_id=1&sid=402907b38e4dc9e1&ssp2=1&stid=9&t=tpclicked3_hc&td=1836545&tu=u1836545&u=http%3A%2F%2Fwww%2Ebubuko%2Ecom%2Finfodetail%2D458771%2Ehtml&urlid=0" target="_blank" mpid="17" style="padding: 0px; color: rgb(51, 51, 51); text-decoration: none;">"padding: 0px; color: rgb(0, 0, 255); width: auto; height: auto;">switch(v.getId())  
  68.         {  
  69.         case R.id.bindServiceButton:  
  70.             bindService();  
  71.             break;  
  72.         case R.id.getServiceButton:  
  73.             getService();     
  74.              break;  
  75.         default:  
  76.              break;  
  77.         }  
  78.     }  
  79.       
  80.       
  81.     private void bindService()  
  82.     {  
  83.         Intent intent=new Intent();  
  84.         intent.setAction(ROOM_SERVICE_ACTION);  
  85.         bindService(intent,conn,BIND_AUTO_CREATE);  
  86.     }  
  87.       
  88.     private void getService()  
  89.     {  
  90.         try  
  91.         {  
  92.             if(mData!=null)  
  93.             {  
  94.                 int roomNum=mData.getRoomNum();  
  95.                 showLongToast("RoomNum:"+roomNum);  
  96.             }  
  97.               
  98.         }  
  99.         catch(RemoteException ex)  
  100.         {  
  101.             ex.printStackTrace();  
  102.         }  
  103.           
  104.     }  
  105.       
  106.     private void showLongToast(String info)  
  107.     {  
  108.         Toast.makeText(getBaseContext(), info, Toast.LENGTH_LONG).show();  
  109.     }  
  110.   
  111.     @Override  
  112.     public boolean onCreateOptionsMenu(Menu menu) {  
  113.         // Inflate the menu; this adds items to the action bar if it is present.  
  114.         getMenuInflater().inflate(R.menu.main, menu);  
  115.         return true;  
  116.     }  
  117.     @Override  
  118.     protected void onDestroy() {  
  119.         // TODO Auto-generated method stub  
  120.         super.onDestroy();  
  121.         unbindService(conn);  
  122.     }  
  123. }  
activity_main.xml的代码如下:

[html]  view plain  copy
  1. <RelativeLayout <span id="14_nwp" style="padding: 0px; width: auto; height: auto; float: none;"><a target=_blank id="14_nwl" href="http://cpro.baidu.com/cpro/ui/uijs.php?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=20&is_app=0&jk=e1c94d8eb3072940&k=xml&k0=xml&kdi0=0&luki=8&mcpm=0&n=10&p=baidu&q=65035100_cpr&rb=0&rs=1&seller_id=1&sid=402907b38e4dc9e1&ssp2=1&stid=9&t=tpclicked3_hc&td=1836545&tu=u1836545&u=http%3A%2F%2Fwww%2Ebubuko%2Ecom%2Finfodetail%2D458771%2Ehtml&urlid=0" target="_blank" mpid="14" style="padding: 0px; color: rgb(51, 51, 51); text-decoration: none;"><span style="padding: 0px; color: rgb(0, 0, 255); width: auto; height: auto;">xmlspan>a>span>ns:android="http://schemas.android.com/apk/<span id="15_nwp" style="padding: 0px; width: auto; height: auto; float: none;"><a target=_blank id="15_nwl" href="http://cpro.baidu.com/cpro/ui/uijs.php?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=20&is_app=0&jk=e1c94d8eb3072940&k=res&k0=res&kdi0=0&luki=9&mcpm=0&n=10&p=baidu&q=65035100_cpr&rb=0&rs=1&seller_id=1&sid=402907b38e4dc9e1&ssp2=1&stid=9&t=tpclicked3_hc&td=1836545&tu=u1836545&u=http%3A%2F%2Fwww%2Ebubuko%2Ecom%2Finfodetail%2D458771%2Ehtml&urlid=0" target="_blank" mpid="15" style="padding: 0px; color: rgb(51, 51, 51); text-decoration: none;"><span style="padding: 0px; color: rgb(0, 0, 255); width: auto; height: auto;">resspan>a>span>/android"  
  2.     xmlns:<span id="16_nwp" style="padding: 0px; width: auto; height: auto; float: none;"><a target=_blank id="16_nwl" href="http://cpro.baidu.com/cpro/ui/uijs.php?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=20&is_app=0&jk=e1c94d8eb3072940&k=tools&k0=tools&kdi0=0&luki=4&mcpm=0&n=10&p=baidu&q=65035100_cpr&rb=0&rs=1&seller_id=1&sid=402907b38e4dc9e1&ssp2=1&stid=9&t=tpclicked3_hc&td=1836545&tu=u1836545&u=http%3A%2F%2Fwww%2Ebubuko%2Ecom%2Finfodetail%2D458771%2Ehtml&urlid=0" target="_blank" mpid="16" style="padding: 0px; color: rgb(51, 51, 51); text-decoration: none;"><span style="padding: 0px; color: rgb(0, 0, 255); width: auto; height: auto;">toolsspan>a>span>="http://schemas.android.com/tools"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     android:paddingBottom="@dimen/activity_vertical_margin"  
  6.     android:paddingLeft="@dimen/activity_horizontal_margin"  
  7.     android:paddingRight="@dimen/activity_horizontal_margin"  
  8.     android:paddingTop="@dimen/activity_vertical_margin"  
  9.     tools:context=".MainActivity" >  
  10.   
  11.     <Button   
  12.         android:id="@+id/bindServiceButton"  
  13.         android:layout_width="fill_parent"  
  14.         android:layout_height="wrap_content"  
  15.         android:text="BindService"  
  16.         />  
  17.     <Button  
  18.         android:id="@+id/getServiceButton"  
  19.         android:layout_width="fill_parent"  
  20.         android:layout_height="wrap_content"  
  21.         android:text="GetService"  
  22.         android:layout_below="@id/bindServiceButton"  
  23.         />  
  24.          
  25. RelativeLayout>  
运行结果如下:

bubuko.com,布布扣

      

       然后举一个稍微复杂一点的栗子,注意如果*.aidl文件中含有自定义的对象,那么该对象的类要实现Parcelable接口,并且要新建一个该类的aidl文件,否则会出现could not find import for class com.android.service.XX的错误,其中XX为类名。还是上面的栗子,但是aidl文件中添加了一些新的方法。仍以上面的RoomService为例,

     Service端的代码如下:

     Room类的代码为:

[java]  view plain  copy
  1. package com.android.service;  
  2.   
  3. import android.os.Parcel;  
  4. import android.os.Parcelable;  
  5.   
  6. public class Room implements Parcelable{  
  7.   
  8.     //房间号  
  9.     private int roomNum;  
  10.     //房间大小  
  11.     private float roomSpace;  
  12.     //是否有空调  
  13.     private boolean hasAirConditioner;  
  14.     //是否有Wifi  
  15.     private boolean hasWifi;  
  16.     //房间内的装饰风格  
  17.     private String decorativeStyle;  
  18.       
  19.     public static final Parcelable.CreatorCREATOR=new Parcelable.Creator() {  
  20.   
  21.         @Override  
  22.         public Room createFromParcel(Parcel source) {  
  23.             return new Room(source);  
  24.         }  
  25.   
  26.         @Override  
  27.         public Room[] newArray(int size) {  
  28.             // TODO Auto-generated method stub  
  29.             return null;  
  30.         }  
  31.           
  32.     };  
  33.       
  34.     public Room(int roomNum,float roomSpace,boolean hasAirConditioner,boolean hasWifi,String decorativeStyle)  
  35.     {  
  36.         this.roomNum=roomNum;  
  37.         this.roomSpace=roomSpace;  
  38.         this.hasAirConditioner=hasAirConditioner;  
  39.         this.hasWifi=hasWifi;  
  40.         this.decorativeStyle=decorativeStyle;  
  41.     }  
  42.       
  43.     private Room(Parcel source)  
  44.     {  
  45.         roomNum=source.readInt();  
  46.         roomSpace=source.readFloat();  
  47.         boolean[]tempArray=new boolean[2];  
  48.         source.readBooleanArray(tempArray);  
  49.        hasAirConditioner=tempArray[0];  
  50.        hasWifi=tempArray[1];  
  51.        decorativeStyle=source.readString();   
  52.     }  
  53.       
  54.     @Override  
  55.     public String toString()  
  56.     {  
  57.         StringBuilder sb=new StringBuilder();  
  58.         sb.append("Basic info of room is as follows:\n");  
  59.         sb.append("RoomNum:"+roomNum+"\n");  
  60.         sb.append("RoomSpace:"+roomSpace+"\n");  
  61.         sb.append("HasAirConditioner:"+hasAirConditioner+"\n");  
  62.         sb.append("HasWifi:"+hasWifi+"\n");  
  63.         sb.append("Decorative Style:"+decorativeStyle);  
  64.         return sb.toString();  
  65.           
  66.     }  
  67.       
  68.     @Override  
  69.     public int describeContents() {  
  70.         // TODO Auto-generated method stub  
  71.         return 0;  
  72.     }  
  73.   
  74.     @Override  
  75.     public void writeToParcel(Parcel dest,int flags) {  
  76.         dest.writeInt(roomNum);  
  77.         dest.writeFloat(roomSpace);  
  78.         dest.writeBooleanArray(new boolean[]{hasAirConditioner,hasWifi});  
  79.         dest.writeString(decorativeStyle);        
  80.     }  
  81.   
  82. }  

Room的声明为:

[java]  view plain  copy
  1. package com.android.service;  
  2. parcelable Room;  

IRoom.aidl的代码为:

[java]  view plain  copy
  1. package com.android.service;  
  2. import com.android.service.Room;  
  3.   
  4. interface IRoom  
  5. {  
  6.   Room getRoom();  
  7. }  
RoomService的代码为:

[java]  view plain  copy
  1. package com.android.service;  
  2.   
  3. import android.app.Service;  
  4. import android.content.Intent;  
  5. import android.os.IBinder;  
  6. import android.os.RemoteException;  
  7.   
  8. public class RoomService extends Service{  
  9.   
  10.     private IRoom.Stub mBinder=new IRoom.Stub() {  
  11.           
  12.         @Override  
  13.         public Room getRoom() throws RemoteException {  
  14.             Room room=new Room(3008,23.5f,true,true,"IKEA");  
  15.             return room;          
  16.         }  
  17.     };  
  18.       
  19.     @Override  
  20.     public IBinder onBind(Intent intent) {  
  21.         return mBinder;  
  22.     }  
  23.   
  24. }  
由于AndroidManifest. xml 的代码不变,因而此处不再贴出。下面是客户端的代码:

[java]  view plain  copy
  1. package com.example.aidlsampleclient;  
  2. import com.android.service.IRoom;  
  3. import android.os.Bundle;  
  4. import android.os.IBinder;  
  5. import android.os.RemoteException;  
  6. import android.app.Activity;  
  7. import android.content.ComponentName;  
  8. import android.content.Intent;  
  9. import android.content.ServiceConnection;  
  10. import android.util.Log;  
  11. import android.view.Menu;  
  12. import android.widget.Button;  
  13. import android.widget.Toast;  
  14. import android.view.View;  
  15.   
  16. public class MainActivity extends Activity implements View.OnClickListener{  
  17.   
  18.       
  19.     private static final String TAG="MainActivity";  
  20.     //private static final String SERVICE_ACTION="com.aidl.service.data";  
  21.     private static final String ROOM_SERVICE_ACTION="com.aidl.service.room";  
  22.       
  23.     private Button bindServiceButton;  
  24.     private Button getServiceButton;  
  25.       
  26.       
  27.     IRoom mRoom;  
  28.       
  29.     private ServiceConnection conn=new ServiceConnection()  
  30.     {  
  31.   
  32.         @Override  
  33.         public void onServiceConnected(ComponentName name, IBinder service) {  
  34.           
  35.             Log.i(TAG,"----------------onServiceConnected--------");  
  36.             showLongToast("onServiceConnected");  
  37.             mRoom=IRoom.Stub.asInterface(service);  
  38.         }  
  39.   
  40.         @Override  
  41.         public void onServiceDisconnected(ComponentName name) {  
  42.           
  43.             Log.i(TAG,"----------------onServiceDisconnected-------------");  
  44.             mRoom=null;  
  45.               
  46.         }  
  47.           
  48.     };  
  49.       
  50.     private void initView()  
  51.     {  
  52.         bindServiceButton=(Button)findViewById(R.id.bindServiceButton);  
  53.         getServiceButton=(Button)findViewById(R.id.getServiceButton);  
  54.         bindServiceButton.setOnClickListener(this);  
  55.         getServiceButton.setOnClickListener(this);  
  56.     }  
  57.     @Override  
  58.     protected void onCreate(Bundle savedInstanceState) {  
  59.         super.onCreate(savedInstanceState);  
  60.         setContentView(R.layout.activity_main);  
  61.         initView();  
  62.     }  
  63.       
  64.     @Override  
  65.     public void onClick(View v) {  
  66.         // TODO Auto-generated method stub  
  67.         "12_nwp" style="padding: 0px; width: auto; height: auto; float: none;">"12_nwl" href="http://cpro.baidu.com/cpro/ui/uijs.php?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=20&is_app=0&jk=e1c94d8eb3072940&k=switch&k0=switch&kdi0=0&luki=10&mcpm=0&n=10&p=baidu&q=65035100_cpr&rb=0&rs=1&seller_id=1&sid=402907b38e4dc9e1&ssp2=1&stid=9&t=tpclicked3_hc&td=1836545&tu=u1836545&u=http%3A%2F%2Fwww%2Ebubuko%2Ecom%2Finfodetail%2D458771%2Ehtml&urlid=0" target="_blank" mpid="12" style="padding: 0px; color: rgb(51, 51, 51); text-decoration: none;">"padding: 0px; color: rgb(0, 0, 255); width: auto; height: auto;">switch(v.getId())  
  68.         {  
  69.         case R.id.bindServiceButton:  
  70.             bindService();  
  71.             break;  
  72.         case R.id.getServiceButton:  
  73.             getService();     
  74.              break;  
  75.         default:  
  76.              break;  
  77.         }  
  78.     }  
  79.       
  80.       
  81.     private void bindService()  
  82.     {  
  83.         Intent intent=new Intent();  
  84.         intent.setAction(ROOM_SERVICE_ACTION);  
  85.         bindService(intent,conn,BIND_AUTO_CREATE);  
  86.     }  
  87.       
  88.     private void getService()  
  89.     {  
  90.         if(mRoom!=null)  
  91.         {  
  92.             try  
  93.             {  
  94.                 showLongToast(mRoom.getRoom().toString());  
  95.             }  
  96.             catch (RemoteException e)   
  97.             {  
  98.                 e.printStackTrace();  
  99.             }  
  100.         }  
  101.   
  102.     }  
  103.       
  104.     private void showLongToast(String info)  
  105.     {  
  106.         Toast.makeText(getBaseContext(), info, Toast.LENGTH_LONG).show();  
  107.     }  
  108.   
  109.     @Override  
  110.     public boolean onCreateOptionsMenu(Menu menu) {  
  111.         // Inflate the menu; this adds items to the action bar if it is present.  
  112.         getMenuInflater().inflate(R.menu.main, menu);  
  113.         return true;  
  114.     }  
  115.     @Override  
  116.     protected void onDestroy() {  
  117.         // TODO Auto-generated method stub  
  118.         super.onDestroy();  
  119.         unbindService(conn);  
  120.     }  
  121. }  

注意首先仍然是要将Room,IRoom的代码复制过去,否则会出错。

运行结果如下:

bubuko.com,布布扣

显然,客户端已经成功读取到服务信息。

注意,上面的所举的栗子其实不只是跨进程,还是跨应用。要注意的是,跨应用一定跨进程,但是跨进程不一定是跨应用。对于跨应用的情况,利用AIDL基本上是较好的解决了问题,但也只是“较好”而已,实际上并不完美,比如,如果要增加一个服务,如果利用AIDL的话,那么又要改写aidl文件,如果是涉及自定义对象,则还要增加自定义对象的声明,而且这种改变不只是Service端的改变,客户端也要跟着改变,显然这种解决方案不够优雅。

        那么,有没有更优雅的方法呢?

        当然有,那就是利用Service的onStartCommand(Intent intent, int flags, int startId)方法。

        服务端代码如下:

 

[java]  view plain  copy
  1. package com.android.service;  
  2.   
  3. import android.app.Service;  
  4. import android.content.BroadcastReceiver;  
  5. import android.content.Context;  
  6. import android.content.Intent;  
  7. import android.content.IntentFilter;  
  8. import android.os.IBinder;  
  9. import android.os.RemoteException;  
  10. import android.util.Log;  
  11. import android.widget.Toast;  
  12.   
  13. public class RoomService extends Service{  
  14.   
  15.     private static final String TAG="RoomService";  
  16.     private static final int CLEAN_SERVICE=0x1;  
  17.     private static final int ORDER_SERVICE=0x2;  
  18.     private static final int PACKAGE_SERVICE=0x3;  
  19.     private static final String SERVICE_KEY="ServiceName";    
  20.     @Override  
  21.     public void onStart(Intent intent, int startId) {  
  22.        showLog("onStart");  
  23.     }  
  24.   
  25.     @Override  
  26.     public int onStartCommand(Intent intent, int flags, int startId) {  
  27.         //String action=intent.getAction();  
  28.         Log.i(TAG,"onStartCommand");  
  29.           
  30.         int actionFlag=intent.getIntExtra(SERVICE_KEY, -1);  
  31.         "11_nwp" style="padding: 0px; width: auto; height: auto; float: none;">"11_nwl" href="http://cpro.baidu.com/cpro/ui/uijs.php?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=20&is_app=0&jk=e1c94d8eb3072940&k=switch&k0=switch&kdi0=0&luki=10&mcpm=0&n=10&p=baidu&q=65035100_cpr&rb=0&rs=1&seller_id=1&sid=402907b38e4dc9e1&ssp2=1&stid=9&t=tpclicked3_hc&td=1836545&tu=u1836545&u=http%3A%2F%2Fwww%2Ebubuko%2Ecom%2Finfodetail%2D458771%2Ehtml&urlid=0" target="_blank" mpid="11" style="padding: 0px; color: rgb(51, 51, 51); text-decoration: none;">"padding: 0px; color: rgb(0, 0, 255); width: auto; height: auto;">switch(actionFlag)  
  32.         {  
  33.         case CLEAN_SERVICE:  
  34.             showShortToast("Start Clean Service Right Now");  
  35.             break;  
  36.         case ORDER_SERVICE:  
  37.             showShortToast("Start Order Service Right Now");  
  38.             break;  
  39.         case PACKAGE_SERVICE:  
  40.             showShortToast("Start Package Service Right Now");  
  41.             break;  
  42.         default:  
  43.             break;  
  44.         }  
  45.         return super.onStartCommand(intent, flags, startId);  
  46.     }  
  47.   
  48.     private void showLog(String info)  
  49.     {  
  50.         Log.i(TAG,info);  
  51.     }  
  52.       
  53.     private void showShortToast(String info)  
  54.     {  
  55.         Toast.makeText(getBaseContext(), info, Toast.LENGTH_SHORT).show();  
  56.     }  
  57.     @Override  
  58.     public void onDestroy() {  
  59.         // TODO Auto-generated method stub  
  60.         showLog("onDestroy");  
  61.         super.onDestroy();  
  62.     }  
  63.   
  64.     @Override  
  65.     public void onCreate() {  
  66.         // TODO Auto-generated method stub  
  67.         showLog("onCreate");  
  68.         super.onCreate();  
  69.     }  
  70.   
  71.   
  72.     @Override  
  73.     public IBinder onBind(Intent intent) {  
  74.         showLog("onBind");  
  75.         return null;  
  76.     }  
  77.   
  78.     @Override  
  79.     public boolean onUnbind(Intent intent) {  
  80.         showLog("onUnbind");  
  81.         return super.onUnbind(intent);  
  82.     }  
  83.       
  84. }  
客户端代码如下:

[java]  view plain  copy
  1. package com.example.aidlsampleclient;  
  2. import com.android.service.IRoom;  
  3. import com.android.service.RoomService;  
  4.   
  5. import android.os.Bundle;  
  6. import android.os.IBinder;  
  7. import android.os.RemoteException;  
  8. import android.app.Activity;  
  9. import android.content.ComponentName;  
  10. import android.content.Intent;  
  11. import android.content.ServiceConnection;  
  12. import android.util.Log;  
  13. import android.view.Menu;  
  14. import android.widget.Button;  
  15. import android.widget.Toast;  
  16. import android.view.View;  
  17.   
  18. public class MainActivity extends Activity implements View.OnClickListener{  
  19.   
  20.     private static final String TAG="MainActivity";  
  21.     private static final String ROOM_SERVICE_ACTION="com.aidl.service.room";  
  22.       
  23.     private static final int CLEAN_SERVICE=0x1;  
  24.     private static final int ORDER_SERVICE=0x2;  
  25.     private static final int PACKAGE_SERVICE=0x3;  
  26.       
  27.     private static final String SERVICE_KEY="ServiceName";  
  28.       
  29.     private Button cleanButton;  
  30.     private Button orderButton;  
  31.     private Button packageButton;  
  32.       
  33.     private void initView()  
  34.     {  
  35.         cleanButton=(Button)findViewById(R.id.cleanButton);  
  36.         orderButton=(Button)findViewById(R.id.orderButton);  
  37.         packageButton=(Button)findViewById(R.id.packageButton);  
  38.       
  39.         cleanButton.setOnClickListener(this);  
  40.         orderButton.setOnClickListener(this);  
  41.         packageButton.setOnClickListener(this);  
  42.     }  
  43.     @Override  
  44.     protected void onCreate(Bundle savedInstanceState) {  
  45.         super.onCreate(savedInstanceState);  
  46.         setContentView(R.layout.activity_main);  
  47.         initView();  
  48.     }  
  49.       
  50.     @Override  
  51.     public void onClick(View v) {  
  52.         // TODO Auto-generated method stub  
  53.         "9_nwp" style="padding: 0px; width: auto; height: auto; float: none;">"9_nwl" href="http://cpro.baidu.com/cpro/ui/uijs.php?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=20&is_app=0&jk=e1c94d8eb3072940&k=switch&k0=switch&kdi0=0&luki=10&mcpm=0&n=10&p=baidu&q=65035100_cpr&rb=0&rs=1&seller_id=1&sid=402907b38e4dc9e1&ssp2=1&stid=9&t=tpclicked3_hc&td=1836545&tu=u1836545&u=http%3A%2F%2Fwww%2Ebubuko%2Ecom%2Finfodetail%2D458771%2Ehtml&urlid=0" target="_blank" mpid="9" style="padding: 0px; color: rgb(51, 51, 51); text-decoration: none;">"padding: 0px; color: rgb(0, 0, 255); width: auto; height: auto;">switch(v.getId())  
  54.         {  
  55.         case R.id.cleanButton:  
  56.             cleanAction();  
  57.             break;  
  58.         case R.id.orderButton:  
  59.             orderAction();  
  60.             break;  
  61.         case R.id.packageButton:  
  62.             packageAction();  
  63.             break;  
  64.         default:  
  65.              break;  
  66.         }  
  67.     }  
  68.           
  69.     private void cleanAction()  
  70.     {  
  71.         startAction(ROOM_SERVICE_ACTION,CLEAN_SERVICE);  
  72.     }  
  73.       
  74.     private void orderAction()  
  75.     {  
  76.         startAction(ROOM_SERVICE_ACTION,ORDER_SERVICE);  
  77.     }  
  78.       
  79.     private void packageAction()  
  80.     {  
  81.         startAction(ROOM_SERVICE_ACTION,PACKAGE_SERVICE);  
  82.     }  
  83.       
  84.     private void startAction(String actionName,int serviceFlag)  
  85.     {  
  86.         //Intent intent=new Intent(this,RoomService.class);  
  87.         Intent intent=new Intent();  
  88.         intent.setAction(actionName);  
  89.         intent.putExtra(SERVICE_KEY, serviceFlag);  
  90.         this.startService(intent);  
  91.     }  
  92.       
  93.     private void showLongToast(String info)  
  94.     {  
  95.         Toast.makeText(getBaseContext(), info, Toast.LENGTH_LONG).show();  
  96.     }  
  97.   
  98.     @Override  
  99.     public boolean onCreateOptionsMenu(Menu menu) {  
  100.         // Inflate the menu; this adds items to the action bar if it is present.  
  101.         getMenuInflater().inflate(R.menu.main, menu);  
  102.         return true;  
  103.     }  
  104.     @Override  
  105.     protected void onDestroy() {  
  106.         // TODO Auto-generated method stub  
  107.         super.onDestroy();  
  108.     }  
  109. }  
运行结果如下:

bubuko.com,布布扣


bubuko.com,布布扣



bubuko.com,布布扣



显然,此时客户端顺利获取了服务。

        上面举的是跨应用的例子,如果是在同一个应用的不同进程的话,则有更简单的实现方法。

        RoomService的代码如下:

[java]  view plain  copy
  1. <"6_nwp" style="padding: 0px; width: auto; height: auto; float: none;">"6_nwl" href="http://cpro.baidu.com/cpro/ui/uijs.php?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=20&is_app=0&jk=e1c94d8eb3072940&k=span&k0=span&kdi0=0&luki=2&mcpm=0&n=10&p=baidu&q=65035100_cpr&rb=0&rs=1&seller_id=1&sid=402907b38e4dc9e1&ssp2=1&stid=9&t=tpclicked3_hc&td=1836545&tu=u1836545&u=http%3A%2F%2Fwww%2Ebubuko%2Ecom%2Finfodetail%2D458771%2Ehtml&urlid=0" target="_blank" mpid="6" style="padding: 0px; color: rgb(51, 51, 51); text-decoration: none;">"padding: 0px; color: rgb(0, 0, 255); width: auto; height: auto;">span "7_nwp" style="padding: 0px; width: auto; height: auto; float: none;">"7_nwl" href="http://cpro.baidu.com/cpro/ui/uijs.php?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=20&is_app=0&jk=e1c94d8eb3072940&k=style&k0=style&kdi0=0&luki=5&mcpm=0&n=10&p=baidu&q=65035100_cpr&rb=0&rs=1&seller_id=1&sid=402907b38e4dc9e1&ssp2=1&stid=9&t=tpclicked3_hc&td=1836545&tu=u1836545&u=http%3A%2F%2Fwww%2Ebubuko%2Ecom%2Finfodetail%2D458771%2Ehtml&urlid=0" target="_blank" mpid="7" style="padding: 0px; color: rgb(51, 51, 51); text-decoration: none;">"padding: 0px; color: rgb(0, 0, 255); width: auto; height: auto;">style="font-size:18px;">package com.android.service;  
  2.   
  3. import com.android.actions.Actions;  
  4.   
  5. import android.app.Service;  
  6. import android.content.BroadcastReceiver;  
  7. import android.content.Context;  
  8. import android.content.Intent;  
  9. import android.content.IntentFilter;  
  10. import android.os.IBinder;  
  11. import android.os.RemoteException;  
  12. import android.util.Log;  
  13. import android.widget.Toast;  
  14.   
  15. public class RoomService extends Service{  
  16.   
  17.     private static final String TAG="RoomService";  
  18.     @Override  
  19.     public void onStart(Intent intent, int startId) {  
  20.        showLog("onStart");  
  21.     }  
  22.   
  23.     @Override  
  24.     public int onStartCommand(Intent intent, int flags, int startId) {  
  25.         //String action=intent.getAction();  
  26.         Log.i(TAG,"onStartCommand");  
  27.         String action=intent.getAction();  
  28.         if(Actions.CLEAN_ACTION.equals(action))  
  29.         {      
  30.             showShortToast("Start Clean Service Right Now");  
  31.         }  
  32.         else if(Actions.ORDER_ACTION.equals(action))  
  33.         {  
  34.             showShortToast("Start Order Service Right Now");  
  35.         }  
  36.         else if(Actions.PACKAGE_ACTION.equals(action))  
  37.         {  
  38.             showShortToast("Start Package Service Right Now");  
  39.         }  
  40.         else  
  41.         {  
  42.             showShortToast("Wrong action");  
  43.         }  
  44.         return super.onStartCommand(intent, flags, startId);  
  45.     }  
  46.   
  47.     private void showLog(String info)  
  48.     {  
  49.         Log.i(TAG,info);  
  50.     }  
  51.       
  52.     private void showShortToast(String info)  
  53.     {  
  54.         Toast.makeText(getBaseContext(), info, Toast.LENGTH_SHORT).show();  
  55.     }  
  56.     @Override  
  57.     public void onDestroy() {  
  58.         // TODO Auto-generated method stub  
  59.         showLog("onDestroy");  
  60.         super.onDestroy();  
  61.     }  
  62.   
  63.     @Override  
  64.     public void onCreate() {  
  65.         // TODO Auto-generated method stub  
  66.         showLog("onCreate");  
  67.         super.onCreate();  
  68.     }  
  69.   
  70.   
  71.     @Override  
  72.     public IBinder onBind(Intent intent) {  
  73.         showLog("onBind");  
  74.         return null;  
  75.     }  
  76.   
  77.     @Override  
  78.     public boolean onUnbind(Intent intent) {  
  79.         showLog("onUnbind");  
  80.         return super.onUnbind(intent);  
  81.     }  
  82.       
  83. }"8_nwp" style="padding: 0px; width: auto; height: auto; float: none;">"8_nwl" href="http://cpro.baidu.com/cpro/ui/uijs.php?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=20&is_app=0&jk=e1c94d8eb3072940&k=span&k0=span&kdi0=0&luki=2&mcpm=0&n=10&p=baidu&q=65035100_cpr&rb=0&rs=1&seller_id=1&sid=402907b38e4dc9e1&ssp2=1&stid=9&t=tpclicked3_hc&td=1836545&tu=u1836545&u=http%3A%2F%2Fwww%2Ebubuko%2Ecom%2Finfodetail%2D458771%2Ehtml&urlid=0" target="_blank" mpid="8" style="padding: 0px; color: rgb(51, 51, 51); text-decoration: none;">"padding: 0px; color: rgb(0, 0, 255); width: auto; height: auto;">span>  

        MainActivity的代码如下:

[java]  view plain  copy
  1. package com.android.activity;  
  2. import com.android.activity.R;  
  3. import com.android.service.RoomService;  
  4.   
  5. import android.app.Activity;  
  6. import android.content.Intent;  
  7. import android.os.Bundle;  
  8. import android.view.Menu;  
  9. import android.widget.Button;  
  10. import android.widget.Toast;  
  11. import android.view.View;  
  12. import com.android.actions.Actions;  
  13.   
  14. public class MainActivity extends Activity implements View.OnClickListener{  
  15.   
  16.     private static final String TAG="MainActivity";  
  17.   
  18.     private static final String SERVICE_KEY="ServiceName";  
  19.       
  20.     private Button cleanButton;  
  21.     private Button orderButton;  
  22.     private Button packageButton;  
  23.       
  24.     private void initView()  
  25.     {  
  26.         cleanButton=(Button)findViewById(R.id.cleanButton);  
  27.         orderButton=(Button)findViewById(R.id.orderButton);  
  28.         packageButton=(Button)findViewById(R.id.packageButton);  
  29.       
  30.         cleanButton.setOnClickListener(this);  
  31.         orderButton.setOnClickListener(this);  
  32.         packageButton.setOnClickListener(this);  
  33.     }  
  34.     @Override  
  35.     protected void onCreate(Bundle savedInstanceState) {  
  36.         super.onCreate(savedInstanceState);  
  37.         setContentView(R.layout.activity_main);  
  38.         initView();  
  39.     }  
  40.       
  41.     @Override  
  42.     public void onClick(View v) {  
  43.         // TODO Auto-generated method stub  
  44.         "4_nwp" style="padding: 0px; width: auto; height: auto; float: none;">"4_nwl" href="http://cpro.baidu.com/cpro/ui/uijs.php?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=20&is_app=0&jk=e1c94d8eb3072940&k=switch&k0=switch&kdi0=0&luki=10&mcpm=0&n=10&p=baidu&q=65035100_cpr&rb=0&rs=1&seller_id=1&sid=402907b38e4dc9e1&ssp2=1&stid=9&t=tpclicked3_hc&td=1836545&tu=u1836545&u=http%3A%2F%2Fwww%2Ebubuko%2Ecom%2Finfodetail%2D458771%2Ehtml&urlid=0" target="_blank" mpid="4" style="padding: 0px; color: rgb(51, 51, 51); text-decoration: none;">"padding: 0px; color: rgb(0, 0, 255); width: auto; height: auto;">switch(v.getId())  
  45.         {  
  46.         case R.id.cleanButton:  
  47.             cleanAction();  
  48.             break;  
  49.         case R.id.orderButton:  
  50.             orderAction();  
  51.             break;  
  52.         case R.id.packageButton:  
  53.             packageAction();  
  54.             break;  
  55.         default:  
  56.              break;  
  57.         }  
  58.     }  
  59.           
  60.     private void cleanAction()  
  61.     {  
  62.         startAction(Actions.CLEAN_ACTION);  
  63.     }  
  64.       
  65.     private void orderAction()  
  66.     {  
  67.         startAction(Actions.ORDER_ACTION);  
  68.     }  
  69.       
  70.     private void packageAction()  
  71.     {  
  72.         startAction(Actions.PACKAGE_ACTION);  
  73.     }  
  74.       
  75.     private void startAction(String actionName)  
  76.     {  
  77.         Intent intent=new Intent(this,RoomService.class);  
  78.         intent.setAction(actionName);  
  79.         this.startService(intent);  
  80.     }  
  81.       
  82.     private void showLongToast(String info)  
  83.     {  
  84.         Toast.makeText(getBaseContext(), info, Toast.LENGTH_LONG).show();  
  85.     }  
  86.   
  87.     @Override  
  88.     public boolean onCreateOptionsMenu(Menu menu) {  
  89.         // Inflate the menu; this adds items to the action bar if it is present.  
  90.         getMenuInflater().inflate(R.menu.main, menu);  
  91.         return true;  
  92.     }  
  93.     @Override  
  94.     protected void onDestroy() {  
  95.         // TODO Auto-generated method stub  
  96.         super.onDestroy();  
  97.     }  
  98. }  

从打印的log可看出,客户端每调用一次Context.startService(Intent),Service就会重新执行一次onStartCommand---->onStart;但是使用AIDL的话,绑定服务之后,不会重复执行onStart,显然后者的代价更小。

Service:前台Service,像我们经常用的天气、音乐其实都利用了前台Service来实现


你可能感兴趣的:(Android 进程间通信的几种实现方式)