android中进程之间通信_android 进程之间的通信 - CSDN
  • Android 几种进程通信方式 如何选择这几种通信方式 ThanksRPC 是什么RPC 即 Remote Procedure Call (远程过程调用) 是一种计算机通讯协议,它为我们定义了计算机 C 的程序如何调用另外一台计算机 S 的程序,让...
    • 不花时间打基础,你将会花更多时间解决那些不必要的问题。

    读完本文你将了解:

    RPC 是什么

    RPC 即 Remote Procedure Call (远程过程调用) 是一种计算机通讯协议,它为我们定义了计算机 C 中的程序如何调用另外一台计算机 S 的程序,让程序员不需要操心底层网络协议,使得开发包括网络分布式多程序在内的应用程序更加容易。

    RPC 是典型的 Client/Server 模式,由客户端对服务器发出若干请求,服务器收到后根据客户端提供的参数进行操作,然后将执行结果返回给客户端。

    RPC 位于 OSI 模型中的会话层:
    这里写图片描述

    在面向对象编程中,它也被叫做 “远程方法调用”。

    IDL 是什么

    RPC 只是一种协议,规定了通信的规则。

    在实际工作中客户端与服务端会有各种各样的平台,就好像日常开发一样,为了统一处理不同的实现,需要定义一个共同的接口,于是有了 IDL。

    IDL 即 Interface Description Language (接口定义语言)。

    它通过一种中立的方式来描述接口,使得在不同平台上运行的对象和用不同语言编写的程序可以相互通信交流。比如,一个组件用 C++ 写成,另一个组件用 Java 写,仍然可以通信。

    这里写图片描述

    IPC 是什么

    IPC 即 Inter-Process Communication (进程间通信)。

    Android 基于 Linux,而 Linux 出于安全考虑,不同进程间不能之间操作对方的数据,这叫做“进程隔离”。

    “进程隔离”更详细的介绍(节选自:http://blog.csdn.net/u010132993/article/details/72582655):

    在 Linux 系统中,虚拟内存机制为每个进程分配了线性连续的内存空间,操作系统将这种虚拟内存空间映射到物理内存空间,每个进程有自己的虚拟内存空间,进而不能操作其他进程的内存空间,只有操作系统才有权限操作物理内存空间。
    进程隔离保证了每个进程的内存安全。

    但是在大多数情形下,不同进程间的数据通讯是不可避免的,因此操作系统必须提供跨进程通信机制。

    Android 几种进程通信方式

    跨进程通信要求把方法调用及其数据分解至操作系统可以识别的程度,并将其从本地进程和地址空间传输至远程进程和地址空间,然后在远程进程中重新组装并执行该调用。

    然后,返回值将沿相反方向传输回来。

    Android 为我们提供了以下几种进程通信机制(供开发者使用的进程通信 API)对应的文章链接如下:

    在上述通信机制的基础上,我们只需集中精力定义和实现 RPC 编程接口即可。

    如何选择这几种通信方式

    《Android 开发艺术探索》中总结的已经比较全面了:

    这里写图片描述

    这里再对比总结一下:

    • 只有允许不同应用的客户端用 IPC 方式调用远程方法,并且想要在服务中处理多线程时,才有必要使用 AIDL
    • 如果需要调用远程方法,但不需要处理并发 IPC,就应该通过实现一个 Binder 创建接口
    • 如果您想执行 IPC,但只是传递数据,不涉及方法调用,也不需要高并发,就使用 Messenger 来实现接口
    • 如果需要处理一对多的进程间数据共享(主要是数据的 CRUD),就使用 ContentProvider
    • 如果要实现一对多的并发实时通信,就使用 Socket

    Thanks

    《Android 开发艺术探索》
    https://zh.wikipedia.org/wiki/%E9%81%A0%E7%A8%8B%E9%81%8E%E7%A8%8B%E8%AA%BF%E7%94%A8
    https://zh.wikipedia.org/wiki/%E6%8E%A5%E5%8F%A3%E6%8F%8F%E8%BF%B0%E8%AF%AD%E8%A8%80
    http://blog.csdn.net/u010132993/article/details/72582655
    https://developer.android.com/guide/components/processes-and-threads.html

    展开全文
  • 在不同应用程序之间交互数据(跨进程通讯),在Android SDK提供了4种用于跨进程通讯的方式。这4种方式正好对应于android系统4种应用程序组件:Activity、Content Provider、Broadcast和Service。其中Activity...

    一、概述

           由于应用程序之间不能共享内存。在不同应用程序之间交互数据(跨进程通讯),在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
     在CODE上查看代码片派生到我的代码片
    1. package com.android.service;  
    2.   
    3. interface IData  
    4. {  
    5.     int getRoomNum();  
    6. }  

    RoomService的代码如下:

    [java] view plain copy
     在CODE上查看代码片派生到我的代码片
    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
     在CODE上查看代码片派生到我的代码片
    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;">xml</span></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;">style</span></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
     在CODE上查看代码片派生到我的代码片
    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.         <span id="17_nwp" style="padding: 0px; width: auto; height: auto; float: none;"><a target=_blank id="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;"><span style="padding: 0px; color: rgb(0, 0, 255); width: auto; height: auto;">switch</span></a></span>(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 p<span id="18_nwp" style="padding: 0px; width: auto; height: auto; float: none;"><a target=_blank id="18_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="18" style="padding: 0px; color: rgb(51, 51, 51); text-decoration: none;"><span style="padding: 0px; color: rgb(0, 0, 255); width: auto; height: auto;">res</span></a></span>ent.  
    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
     在CODE上查看代码片派生到我的代码片
    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;">xml</span></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;">res</span></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;">tools</span></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
     在CODE上查看代码片派生到我的代码片
    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.Creator<Room>CREATOR=new Parcelable.Creator<Room>() {  
    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
     在CODE上查看代码片派生到我的代码片
    1. package com.android.service;  
    2. parcelable Room;  

    IRoom.aidl的代码为:

    [java] view plain copy
     在CODE上查看代码片派生到我的代码片
    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
     在CODE上查看代码片派生到我的代码片
    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
     在CODE上查看代码片派生到我的代码片
    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.         <span id="12_nwp" style="padding: 0px; width: auto; height: auto; float: none;"><a target=_blank id="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;"><span style="padding: 0px; color: rgb(0, 0, 255); width: auto; height: auto;">switch</span></a></span>(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 p<span id="13_nwp" style="padding: 0px; width: auto; height: auto; float: none;"><a target=_blank id="13_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="13" style="padding: 0px; color: rgb(51, 51, 51); text-decoration: none;"><span style="padding: 0px; color: rgb(0, 0, 255); width: auto; height: auto;">res</span></a></span>ent.  
    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
     在CODE上查看代码片派生到我的代码片
    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.         <span id="11_nwp" style="padding: 0px; width: auto; height: auto; float: none;"><a target=_blank id="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;"><span style="padding: 0px; color: rgb(0, 0, 255); width: auto; height: auto;">switch</span></a></span>(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
     在CODE上查看代码片派生到我的代码片
    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.         <span id="9_nwp" style="padding: 0px; width: auto; height: auto; float: none;"><a target=_blank id="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;"><span style="padding: 0px; color: rgb(0, 0, 255); width: auto; height: auto;">switch</span></a></span>(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 p<span id="10_nwp" style="padding: 0px; width: auto; height: auto; float: none;"><a target=_blank id="10_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="10" style="padding: 0px; color: rgb(51, 51, 51); text-decoration: none;"><span style="padding: 0px; color: rgb(0, 0, 255); width: auto; height: auto;">res</span></a></span>ent.  
    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
     在CODE上查看代码片派生到我的代码片
    1. <<span id="6_nwp" style="padding: 0px; width: auto; height: auto; float: none;"><a target=_blank id="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;"><span style="padding: 0px; color: rgb(0, 0, 255); width: auto; height: auto;">span</span></a></span> <span id="7_nwp" style="padding: 0px; width: auto; height: auto; float: none;"><a target=_blank id="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;"><span style="padding: 0px; color: rgb(0, 0, 255); width: auto; height: auto;">style</span></a></span>="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. }</<span id="8_nwp" style="padding: 0px; width: auto; height: auto; float: none;"><a target=_blank id="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;"><span style="padding: 0px; color: rgb(0, 0, 255); width: auto; height: auto;">span</span></a></span>>  

            MainActivity的代码如下:

    [java] view plain copy
     在CODE上查看代码片派生到我的代码片
    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.         <span id="4_nwp" style="padding: 0px; width: auto; height: auto; float: none;"><a target=_blank id="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;"><span style="padding: 0px; color: rgb(0, 0, 255); width: auto; height: auto;">switch</span></a></span>(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 p<span id="5_nwp" style="padding: 0px; width: auto; height: auto; float: none;"><a target=_blank id="5_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="5" style="padding: 0px; color: rgb(51, 51, 51); text-decoration: none;"><span style="padding: 0px; color: rgb(0, 0, 255); width: auto; height: auto;">res</span></a></span>ent.  
    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 SDK提供了4种用于跨进程通讯的方式。这4种方式正好对应于android系统4种应用程序组件:Activity、Content Provider、Broadcast和Service。其中Activity...

    一、概述

           由于应用程序之间不能共享内存。在不同应用程序之间交互数据(跨进程通讯),在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;">xml</span></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;">style</span></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.         <span id="17_nwp" style="padding: 0px; width: auto; height: auto; float: none;"><a target=_blank id="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;"><span style="padding: 0px; color: rgb(0, 0, 255); width: auto; height: auto;">switch</span></a></span>(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 p<span id="18_nwp" style="padding: 0px; width: auto; height: auto; float: none;"><a target=_blank id="18_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="18" style="padding: 0px; color: rgb(51, 51, 51); text-decoration: none;"><span style="padding: 0px; color: rgb(0, 0, 255); width: auto; height: auto;">res</span></a></span>ent.  
    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;">xml</span></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;">res</span></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;">tools</span></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.Creator<Room>CREATOR=new Parcelable.Creator<Room>() {  
    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.         <span id="12_nwp" style="padding: 0px; width: auto; height: auto; float: none;"><a target=_blank id="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;"><span style="padding: 0px; color: rgb(0, 0, 255); width: auto; height: auto;">switch</span></a></span>(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 p<span id="13_nwp" style="padding: 0px; width: auto; height: auto; float: none;"><a target=_blank id="13_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="13" style="padding: 0px; color: rgb(51, 51, 51); text-decoration: none;"><span style="padding: 0px; color: rgb(0, 0, 255); width: auto; height: auto;">res</span></a></span>ent.  
    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.         <span id="11_nwp" style="padding: 0px; width: auto; height: auto; float: none;"><a target=_blank id="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;"><span style="padding: 0px; color: rgb(0, 0, 255); width: auto; height: auto;">switch</span></a></span>(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;