该学习笔记根据一个网友的例子整理而成。
(1)服务器端
1.创建一个AIDL文件,可以看提供的源码。创建完成后,eclipse插件自动在gen目录下生成同名字的java文件。里面包含一个Stub抽象类,这个类继承自android.os.Binder,这个类是实现整个远程调用的核心。
// 声明Java包头,该AIDL文件会生成对应的Java类,并置于gen目录下 package com.hdu.edu.aidltest; // 接口声明 interface IPerson { void setAge(int age); void setName(String name); String display(); }
2.然后创建一个类来继承上面说到的那个Stub抽象类,实现里面的抽象方法。(这些抽象方法是根据AIDL文件自动生成的)。
package com.hdu.edu.aidltest; import android.os.RemoteException; public class IPersonImpl extends IPerson.Stub{ private String name = "default name"; private int age = 10; @Override public void setAge(int age) throws RemoteException { this.age = age; } @Override public void setName(String name) throws RemoteException { this.name = name; } @Override public String display() throws RemoteException { StringBuilder sb = new StringBuilder(); sb.append(age).append(name); return sb.toString(); } }
3.创建一个自定义Service继承自Service,实现其onBind方法,注意此onBind方法必须返回第二步创建的那个Stub类的子类。然后在xml中声明此service,注意此service的声明必须包含一个action,此action也用于客户端的调用使用。(在下面的客户端开发中会有介绍)。
package com.hdu.edu.aidltest; import android.app.Service; import android.content.Intent; import android.os.Binder; import android.os.IBinder; public class RemoteService extends Service { // 声明IPerson接口 private Binder iPerson = new IPersonImpl(); @Override // 如果调用者通过Context.bindService函数来绑定服务组件建立连接,那么 // Service.onStartCommand函数将不会被调用,而onBind函数将会被调用, // onBind函数会接收到通过bindService函数传递过来的Intent对象,依照Intent // 对象的不同,onBind函数将会返回对应的IBinder对象。在下面的实现中是直接返回一个 // Binder对象。以上这个绑定过程是一个异步操作,组件管理服务参与其中的调度。bindService // 函数不会等待绑定确认便直接返回,onBind函数返回的IBinder对象,会通过回调android.content. // ServiceConnection对象的onServiceConnected方法传递给调用者。调用者拿到这个 // IBinder对象后,就可以通过它与服务组件进行远程方法调用。 public IBinder onBind(Intent intent) { return iPerson; } }
4.创建一个Activity,此Activity只要实现把Service启动了即可。(其实这里并不需要这个Activity来启动这个Service)
这样服务器端就开发完毕,运行后启动了一个可供远程调用的Service。关键还是通过onBind暴露一个Binder给客户端。Binder哪来呢?就是通过AIDL文件adt会自动生成一个抽象类Stub继承自Binder,只需要创建一个类实现这个Stub的抽象方法即可。
(2)然后开发客户端:
1.客户端也需要一个AIDL文件,注意客户端的aidl文件的包名必须和服务器端的aidl包名一致,名字也相同。创建完后同样会在gen下生成一个接口。
2.创建一个Activity,包含变量ServiceConnection con,实现其onServiceConnected和onServiceDisconnected方法,onServiceConnected方法生成第一步那个接口的实现类的对象。con对象用于在onCreate中绑定service,这个service的action必须为服务器端声明的那个service的配置action。绑定中用到con会执行onServiceConnected方法生成AIDL对象iPerson。然后就可以通过iPerson来调用aidl里的任意方法返回服务器的东西。
package com.hdu.edu.aidltestclient; public class MainActivity extends Activity implements OnClickListener{ // 声明IPerson接口 private IPerson iPerson; // 实例化ServiceConnection private ServiceConnection conn = new ServiceConnection() { @Override synchronized public void onServiceConnected(ComponentName name, IBinder service) { // 获得IPerson接口 iPerson = IPerson.Stub.asInterface(service); } @Override public void onServiceDisconnected(ComponentName name) { iPerson=null; } }; Button setAge; Button setName; Button display; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initUI(); // 设置Intent Action 属性 Intent intent = new Intent("com.hdu.edu.aidltest.action.MY_REMOTE_SERVICE"); bindService(intent, conn, Service.BIND_AUTO_CREATE); } private void initUI() { setAge = (Button) findViewById(R.id.setAge); setName = (Button) findViewById(R.id.setName); display = (Button) findViewById(R.id.display); setAge.setOnClickListener(this); setName.setOnClickListener(this); display.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.display: try { String msg = iPerson.display(); Toast.makeText(this, msg, Toast.LENGTH_LONG).show(); } catch (RemoteException e) { e.printStackTrace(); } break; case R.id.setAge: try { iPerson.setAge(30); } catch (RemoteException e) { e.printStackTrace(); } break; case R.id.setName: try { iPerson.setName("new Name"); } catch (RemoteException e) { e.printStackTrace(); } break; default: break; } } @Override protected void onDestroy() { // 关闭连接,当组件服务不再有连接后,组件管理服务会选择时机销毁该服务组件对象 unbindService(conn); super.onDestroy(); } }
客户端开发完毕。关键点是创建aidl文件自动生成了一个接口,在activity中必须绑定服务程序开启的service,在绑定过程中初始化AIDL对象。然后就可用AIDL对象调用任意方法了。
(3)服务组件的进程间通信模型:当界面组件(Activity)和服务组件(Service)绑定后,进程会通过方法的调用进行通信。而在实际应用中,前台界面组件和后台服务组件可能来自不同的应用,这就需要进行进程间通信。Android的进程间模型,主要包含三方面的内容:
1.Android的进程间通信模型架构:该模型和传统的远程通信模型非常相似,是典型的代理模式(Proxy Pattern)。在Android中,开发者将需要进行远程通信的接口定义成android.os.IInterface接口的子类型(即图中的MY_API)。该类型会有两个实现者:用在调用者一端的MY_API.Proxy(简称为Proxy对象)和用在功能实现者这一端的MY_API.Sub(简称Sub对象)。具体过程如下图所示:
图1 Android的进程间通信模型
在界面组件和服务组件绑定的流程中,界面组件可以通过Context.bindService获得IBinder的对象,通过它的静态方法asInterface可以获得Proxy对象实例。界面段使用Proxy对象,就可以实现对服务端功能的远程调用。对于IPC方法的调用是一个同步的流程,如果执行时间太长,就会阻塞调用方的线程,这时候需要用到异步IPC调用。请看下面的流程图:
图2 Android的进程间异步方法调用
2.框架代码自动生成(AIDL):以上整个进程通信模型中有固定的类型和方法需要实现,包含很多雷同的序列化和反序列化操作。这些工作要通过自动化的手段来完成。在Android中,是通过AIDL的帮助来自动完成 这些框架代码的。Android SDK中提供了AIDL的解析工具,它会根据所提供的AIDL文件,自动生成对应的MY_API、MY_API.Proxy、MY_API.Sub等类型的Java文件。开发者只要继承MY_API.Sub,实现Implement类型。
// 声明Java包头,该AIDL文件会生成对应的Java类,并放在gen目录下 package com.xxx.xxxx; // 声明导入的包,通常是另一个AIDL生成的类,用于异步调用函数 import com.xxx.xxxx.ICallback; // 接口声明 interface IMyApi { // 一个简单的参数同步方法 int getId(in String name); // 一个带有输入输出参数的同步方法 void getIds(in String[] names, out Long[] values); // 一个异步方法 void asyncGetId(in String name, in ICallback callback); }
3.参数序列化:数据的序列化和反序列化是所有进程间通信的基础。在Android中,负责这项任务的是android.os.Parcel类,它提供了一系列的write和read接口,支持多种类型数据的序列化操作。
相关推荐
aidl跨进程调用
android项目之aidl跨进程调用举例Demo,开发aidl跨进程调用,主要分以下步骤: 1. 创建.aidl文件-该文件(YourInterface.aidl)定义了客户端可用的方法和数据的接口。 2. 在makefile文件中加入.aidl文件-(Eclipse...
Androidaidl跨进程调用.zip源码资源下载Androidaidl跨进程调用.zip源码资源下载
Androidaidl跨进程调用.zip项目安卓应用源码下载Androidaidl跨进程调用.zip项目安卓应用源码下载 1.适合学生毕业设计研究参考 2.适合个人学习研究参考 3.适合公司开发项目技术参考
aidl跨进程调用
AIDL是Android中IPC(Inter-Process Communication)方式中的一种,AIDL是Android Interface definition language的缩写,对于小白来说,AIDL的作用是让你可以在自己的APP里绑定一个其他APP的service,这样你的APP...
Android程序研发源码aidl跨进程调用.zip
Androidaidl跨进程调用.zip
安卓Android源码——aidl跨进程调用.zip
Android aidl跨进程调用.zip
aidl跨进程调用 Android源码.rar
aidl跨进程调用.zip
安卓开发-aidl跨进程调用.zip
Android源码——aidl跨进程调用.zip
安卓Android源码——精典源码之aidl跨进程调用.zip
android aidl跨进程通信例子,简单明了
Android应用源码开发Demo,主要用于毕业设计学习。