玩转Andorid---组件篇---Service(服务)之RPC远程进程调用

来源:互联网 发布:数据库入门 编辑:程序博客网 时间:2024/06/05 15:04

原址:http://hualang.iteye.com/category/143855

在Andorid平台中,各个组件运行在自己的进程中,他们之间是不能相互访问的,但是在程序之间是不可避免的要传递一些对象,在进程之间相互通信。为了实现进程之间的相互通信,Andorid采用了一种轻量级的实现方式RPC(Remote Procedure Call 远程进程调用)来完成进程之间的通信,并且Android通过接口定义语言(Andorid Interface Definition Language ,AIDL)来生成两个进程之间相互访问的代码,例如,你在Activity里的代码需要访问Service中的一个方法,那么就可以通过这种方式来实现了。

AIDL RPC机制是通过接口来实现的,类似Windows中的COM或者Corba,但他是轻量级的,客户端和被调用实现之间是通过代理模式实现的,代理类和被代理类实现同一个接口Ibinder接口。

 

实例练习:

<!--[if !supportLists]-->1、  <!--[endif]-->创建一个项目,在包中创建一个AIDL文件,定义一个AIDL文件的语法和定义一个JAVA接口的语法类似,只不过文件的扩展名是“.aidl”。在AIDL文件中可以声明任一多个方法,方法可以带参数,也可以有返回值,参数和返回值是任意类型。需要注意的是,你必须导入除了内建类型(例如:int,boolean等)外的任何其他类型,即使他们在同一个包中,具体规则如下:

<!--[if !supportLists]-->①     <!--[endif]-->JAVA原始类型不需要导入

<!--[if !supportLists]-->②     <!--[endif]-->String,List,Map和CharSequence不需要导入

定义好的 AIDL文件可以使用ADT插件自动生成java代码

 

现在开始写代码:

创建一个名字为IPerson.aidl的文件

 

Java代码  收藏代码
  1. package org.hualang.rpc;  
  2.   
  3. //IPerson接口  
  4. interface IPerson  
  5. {  
  6.     //设置年龄  
  7.     void setAge(int age);  
  8.     //设置姓名方法  
  9.     void setName(String name);  
  10.     //显示信息方法  
  11.     String display();  
  12. }  

 2、当创建好这个文件后,刷新工程,就会在gen目录下看到这个java接口



 当你分析了这个代码后会发现,它是使用的代理模式来实现的,我们一般定义该接口的静态内部类Stub的asInterface()方法,返回我们的接口

3、实现AIDL文件生成的JAVA接口

AIDL会生成一个和.aidl文件同名的JAVA接口文件,该接口中有一个静态抽象内部类Stub,该类中声明了AIDL文件中定义的所有方法,其中有一个重要的方法是asInterface(),该方法通过代理模式返回JAVA接口的实现

我们可以定义一个实现类,PerionImpl,该类继承Stub类,实现我们定义的3个方法

Java代码  收藏代码
  1. /** 
  2.  * @author hualang 
  3.  * IPerson接口实现类 
  4.  */  
  5. package org.hualang.rpc;  
  6.   
  7. import android.os.RemoteException;  
  8.   
  9. public class IPersonImpl extends IPerson.Stub {  
  10.     //声明两个变量  
  11.     private int age;  
  12.     private String name;  
  13.     //显示name和age  
  14.     public String display() throws RemoteException  
  15.     {  
  16.         return "name="+name+";age="+age;  
  17.     }  
  18.     @Override  
  19.     public void setAge(int age) throws RemoteException {  
  20.         // TODO Auto-generated method stub  
  21.         this.age = age;  
  22.     }  
  23.   
  24.     @Override  
  25.     public void setName(String name) throws RemoteException {  
  26.         // TODO Auto-generated method stub  
  27.         this.name = name;  
  28.     }  
  29.       
  30. }  

 4、将你的接口暴露给客户端

现在我们已经实现了IPerson接口,接下俩我们要看看如何将该接口暴露给客户端调用。一般我们通过定义一个Service来实现,在Service的onBind()方法中返回该接口,当我们板顶该接口时调用该方法。

Java代码  收藏代码
  1. /** 
  2.  * @author hualang 
  3.  * 使用Service将接口暴露给客户端 
  4.  */  
  5. package org.hualang.rpc;  
  6.   
  7. import org.hualang.rpc.IPerson.Stub;  
  8.   
  9. import android.app.Service;  
  10. import android.content.Intent;  
  11. import android.os.IBinder;  
  12.   
  13. public class RemoteService extends Service {  
  14.     //声明IPerson接口  
  15.     private Stub iperson = new IPersonImpl();  
  16.     public IBinder onBind(Intent intent)  
  17.     {  
  18.         return iperson;  
  19.     }  
  20. }  

 5、客户端调用

接下来定义一个Activity来绑定远程Service,获得IPerson接口,通过RPC机制调用接口中的方法。

Java代码  收藏代码
  1. /** 
  2.  * @author hualang 
  3.  * IPerson接口实现类 
  4.  */  
  5. package org.hualang.rpc;  
  6.   
  7. import android.app.Activity;  
  8. import android.app.Service;  
  9. import android.content.ComponentName;  
  10. import android.content.Intent;  
  11. import android.content.ServiceConnection;  
  12. import android.os.Bundle;  
  13. import android.os.IBinder;  
  14. import android.os.RemoteException;  
  15. import android.view.View;  
  16. import android.view.View.OnClickListener;  
  17. import android.widget.Button;  
  18. import android.widget.Toast;  
  19.   
  20. public class RPCTest extends Activity {  
  21.     /** Called when the activity is first created. */  
  22.     private IPerson iPerson;  
  23.     private Button btn;  
  24.     private ServiceConnection conn = new ServiceConnection()  
  25.     {  
  26.         synchronized public void onServiceConnected(ComponentName name, IBinder service) {  
  27.             // 获得IPerson接口  
  28.             iPerson = IPerson.Stub.asInterface(service);  
  29.             if (iPerson != null)  
  30.                 try {  
  31.                     // RPC 方法调用  
  32.                     iPerson.setName("花郎");  
  33.                     iPerson.setAge(22);  
  34.                     String msg = iPerson.display();  
  35.                     // 显示方法调用返回值  
  36.                     Toast.makeText(RPCTest.this, msg, Toast.LENGTH_LONG)  
  37.                             .show();  
  38.                 } catch (RemoteException e) {  
  39.                     e.printStackTrace();  
  40.                 }  
  41.         }  
  42.   
  43.         @Override  
  44.         public void onServiceDisconnected(ComponentName name) {  
  45.             // TODO Auto-generated method stub  
  46.               
  47.         }  
  48.           
  49.     };  
  50.     //声明IPerson接口  
  51.     @Override  
  52.     public void onCreate(Bundle savedInstanceState) {  
  53.         super.onCreate(savedInstanceState);  
  54.         setContentView(R.layout.main);  
  55.         btn = (Button)findViewById(R.id.Button01);  
  56.         btn.setOnClickListener(new OnClickListener()  
  57.         {  
  58.   
  59.             @Override  
  60.             public void onClick(View v) {  
  61.                 // TODO Auto-generated method stub  
  62.                 Intent intent = new Intent();  
  63.                 intent.setAction("org.hualang.rpc.RPC_ACTION");  
  64.                 bindService(intent, conn, Service.BIND_AUTO_CREATE);  
  65.             }  
  66.               
  67.         }  
  68.        );  
  69.     }  
  70. }  

 6、注意要在AndroidManifest.xml文件中注册Service

Java代码  收藏代码
  1. <service  
  2.     android:name=".RemoteService">  
  3.     <intent-filter>  
  4.         <action android:name="org.hualang.rpc.RPC_ACTION"/>  
  5.     </intent-filter>  
  6. </service>  

 

运行结果如下:当点击按钮后,就会弹出远程调用后的Toast


 

 


0 0
原创粉丝点击