原址: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的文件
- package org.hualang.rpc;
- //IPerson接口
- interface IPerson
- {
- //设置年龄
- void setAge(int age);
- //设置姓名方法
- void setName(String name);
- //显示信息方法
- String display();
- }
2、当创建好这个文件后,刷新工程,就会在gen目录下看到这个java接口
当你分析了这个代码后会发现,它是使用的代理模式来实现的,我们一般定义该接口的静态内部类Stub的asInterface()方法,返回我们的接口
3、实现AIDL文件生成的JAVA接口
AIDL会生成一个和.aidl文件同名的JAVA接口文件,该接口中有一个静态抽象内部类Stub,该类中声明了AIDL文件中定义的所有方法,其中有一个重要的方法是asInterface(),该方法通过代理模式返回JAVA接口的实现
我们可以定义一个实现类,PerionImpl,该类继承Stub类,实现我们定义的3个方法
- /**
- * @author hualang
- * IPerson接口实现类
- */
- package org.hualang.rpc;
- import android.os.RemoteException;
- public class IPersonImpl extends IPerson.Stub {
- //声明两个变量
- private int age;
- private String name;
- //显示name和age
- public String display() throws RemoteException
- {
- return "name="+name+";age="+age;
- }
- @Override
- public void setAge(int age) throws RemoteException {
- // TODO Auto-generated method stub
- this.age = age;
- }
- @Override
- public void setName(String name) throws RemoteException {
- // TODO Auto-generated method stub
- this.name = name;
- }
- }
4、将你的接口暴露给客户端
现在我们已经实现了IPerson接口,接下俩我们要看看如何将该接口暴露给客户端调用。一般我们通过定义一个Service来实现,在Service的onBind()方法中返回该接口,当我们板顶该接口时调用该方法。
- /**
- * @author hualang
- * 使用Service将接口暴露给客户端
- */
- package org.hualang.rpc;
- import org.hualang.rpc.IPerson.Stub;
- import android.app.Service;
- import android.content.Intent;
- import android.os.IBinder;
- public class RemoteService extends Service {
- //声明IPerson接口
- private Stub iperson = new IPersonImpl();
- public IBinder onBind(Intent intent)
- {
- return iperson;
- }
- }
5、客户端调用
接下来定义一个Activity来绑定远程Service,获得IPerson接口,通过RPC机制调用接口中的方法。
- /**
- * @author hualang
- * IPerson接口实现类
- */
- package org.hualang.rpc;
- import android.app.Activity;
- import android.app.Service;
- import android.content.ComponentName;
- import android.content.Intent;
- import android.content.ServiceConnection;
- import android.os.Bundle;
- import android.os.IBinder;
- import android.os.RemoteException;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.widget.Button;
- import android.widget.Toast;
- public class RPCTest extends Activity {
- /** Called when the activity is first created. */
- private IPerson iPerson;
- private Button btn;
- private ServiceConnection conn = new ServiceConnection()
- {
- synchronized public void onServiceConnected(ComponentName name, IBinder service) {
- // 获得IPerson接口
- iPerson = IPerson.Stub.asInterface(service);
- if (iPerson != null)
- try {
- // RPC 方法调用
- iPerson.setName("花郎");
- iPerson.setAge(22);
- String msg = iPerson.display();
- // 显示方法调用返回值
- Toast.makeText(RPCTest.this, msg, Toast.LENGTH_LONG)
- .show();
- } catch (RemoteException e) {
- e.printStackTrace();
- }
- }
- @Override
- public void onServiceDisconnected(ComponentName name) {
- // TODO Auto-generated method stub
- }
- };
- //声明IPerson接口
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- btn = (Button)findViewById(R.id.Button01);
- btn.setOnClickListener(new OnClickListener()
- {
- @Override
- public void onClick(View v) {
- // TODO Auto-generated method stub
- Intent intent = new Intent();
- intent.setAction("org.hualang.rpc.RPC_ACTION");
- bindService(intent, conn, Service.BIND_AUTO_CREATE);
- }
- }
- );
- }
- }
6、注意要在AndroidManifest.xml文件中注册Service
- <service
- android:name=".RemoteService">
- <intent-filter>
- <action android:name="org.hualang.rpc.RPC_ACTION"/>
- </intent-filter>
- </service>
运行结果如下:当点击按钮后,就会弹出远程调用后的Toast