aidl可用于进程间的通讯,我们都知道一个安卓应用程序对应一个虚拟机,原则上是不允许不同的虚拟机之间通信的,这时候就出来远程服务aidl它可以进行不同进程间的通讯。
aidl它其实是一种语言IPC,是通过binder实现的(具体原理下一篇中讲解)
下面我们来看一个晓得例子:
新建一个项目起名为远程服务:
RemoteService:
这个远程服务要被另外一个项目调用:
第一步创建一个远程服务RemoteService集成Service代码如下:
package com.example.aidl;
import com.example.aidl.invoke.IService;
import com.example.aidl.invoke.IService.Stub;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
/**
* 远程服务
* @author Administrator
*
*/
public class RemoteService extends Service {
@Override
public IBinder onBind(Intent arg0) {
return new MyBinder();
}
// 业务逻辑方法
public void serviceMethod(){
System.out.println("*************************");
}
// 创建一个供外部调用逻辑的中间类
private class MyBinder extends Stub{
@Override
public void callMethod() {
//调用服务的业务逻辑方法
serviceMethod();
}
}
}
上面代码中中间类刚开始是继承IService的,刚开始是创建的IService是一个接口扩展名是Java的,如下:
package com.example.aidl.invoke;
/**
* 供外面调用的接口
* @author Administrator
*
*/
interface IService {
/**
* 供外面操作调用的方法
*/
void callMethod();
}
然后再远程项目中测试一下服务,看是否好使,代码如下:
package com.example.aidl;
import com.example.aidl.invoke.IService;
import android.app.Activity;
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;
public class MainActivity extends Activity {
private IService myBinder;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
//绑定服务
public void bindService(View v){
// 测试一下绑定的服务
Intent intent = new Intent(this,RemoteService.class);
bindService(intent, new MyConntion(), BIND_AUTO_CREATE);
}
//本地调用服务中的方法
public void callServiceMethod(View v){
//调用服务中的业务逻辑方法
try {
myBinder.callMethod();
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 实现服务的连接
* @author Administrator
*
*/
private class MyConntion implements ServiceConnection{
@Override
public void onServiceConnected(ComponentName arg0, IBinder arg1) {
myBinder = (IService) arg1;
}
@Override
public void onServiceDisconnected(ComponentName arg0) {
}
}
}
接下来开始在创建一个项目
这里需要把上面远程服务所在的项目的IService的扩展名改为aidl
package com.example.aidl.invoke;
/**
* 供外面调用的接口
* @author Administrator
*
*/
interface IService {
/**
* 供外面操作调用的方法
*/
void callMethod();
}
把这个扩展名为aidl的文件复制到NativeAPP中,注意连同包名一起复制,这里有个小问题,就是在清单文件中需要价格action:
<service android:name="com.example.aidl.RemoteService">
<intent-filter >
<action android:name="com.example.aidl.fly"/>
</intent-filter>
</service>
再说明一点,扩展名改为aidl的时候,会在gen文件下面生成一个文件:
/*
* This file is auto-generated. DO NOT MODIFY.
* Original file: D:\\android_EclipseDemo\\RemoteService\\src\\com\\example\\aidl\\invoke\\IService.aidl
*/
package com.example.aidl.invoke;
/**
* 供外面调用的接口
* @author Administrator
*
*/
public interface IService extends android.os.IInterface
{
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements com.example.aidl.invoke.IService
{
private static final java.lang.String DESCRIPTOR = "com.example.aidl.invoke.IService";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an com.example.aidl.invoke.IService interface,
* generating a proxy if needed.
*/
public static com.example.aidl.invoke.IService asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.example.aidl.invoke.IService))) {
return ((com.example.aidl.invoke.IService)iin);
}
return new com.example.aidl.invoke.IService.Stub.Proxy(obj);
}
@Override public android.os.IBinder asBinder()
{
return this;
}
@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
{
switch (code)
{
case INTERFACE_TRANSACTION:
{
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_callMethod:
{
data.enforceInterface(DESCRIPTOR);
this.callMethod();
reply.writeNoException();
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
private static class Proxy implements com.example.aidl.invoke.IService
{
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote)
{
mRemote = remote;
}
@Override public android.os.IBinder asBinder()
{
return mRemote;
}
public java.lang.String getInterfaceDescriptor()
{
return DESCRIPTOR;
}
/**
* 供外面操作调用的方法
*/
@Override public void callMethod() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_callMethod, _data, _reply, 0);
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}
}
static final int TRANSACTION_callMethod = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
}
/**
* 供外面操作调用的方法
*/
public void callMethod() throws android.os.RemoteException;
}
重点看这里:
public static abstract class Stub extends android.os.Binder implements com.example.aidl.invoke.IService
{
也就是在代码中不需要去实现IService这个接口,直接继承Stub这个类就好了,
在NativeAPP项目中调用远程服务的方法:
package com.example.nativeapp;
import com.example.aidl.invoke.IService;
import com.example.aidl.invoke.IService.Stub;
import android.app.Activity;
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;
public class MainActivity extends Activity {
private IService asInterface;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void bindService(View v){
// 隐士意图启动服务
Intent intent = new Intent();
intent.setAction("com.example.aidl.fly");
bindService(intent, new MyConntion(), BIND_AUTO_CREATE);
}
//远程服务调用的方法
public void callServiceMethod(View v){
try {
asInterface.callMethod();
} catch (RemoteException e) {
e.printStackTrace();
}
}
/**
* 服务连接
* @author Administrator
*
*/
private class MyConntion implements ServiceConnection{
@Override
public void onServiceConnected(ComponentName arg0, IBinder arg1) {
asInterface = Stub.asInterface(arg1);
}
@Override
public void onServiceDisconnected(ComponentName arg0) {
}
}
}
这样就基本实现了aidl跨进程通信。