Andoid AIDL学习

  AIDL学习

1.什么是aidl:

AIDL是 Android Interface definition language的缩写,一看就明白,它是一种android内部进程通信接口的描述语言,通过它我们可以定义进程间的通信接口

ps:以前用过万恶的RMI,比较类似

其他名词补充:
ICP:interprocess communication :内部进程通信 

2.什么时候使用AIDL?

AIDL 主要用于进程间访问、调用的时候

比如自己写了一个应用,想在自己的这个应用里面调用系统的挂断电话的方法。

这是两个应用两个进程间的调用

---------------------------割割-------------------------------

经过实践证明 如果做播放器,不用AIDL技术是完全也是可以实现的。

如果本service只作为本地调用,可无须关于aidl相关操作,服务端的binder直接像stub那样,即使binder又是service,这样,调用方(如Activity)由于与该service在同一个apk中,ServiceConnection中获取的clientBind就是service返回的那个myBinder,这样的话,直接强转即可得到IMyBizService.不用调用queryLocalInterface()方法再查找一次。


No1.首先定义一个接口文件IService.java,内容如下:

 

  
  
  
  
  1. public interface IService { 
  2.  
  3.     public void callMethodInService(); 

 

No2.在相应的Service中定义一个Binder子类,并实现Iservice接口中的方法:

注意MyBinder类继承自Binder类

 

   
   
   
   
  1. class MyBinder extends Binder implements IService{ 
  2.  
  3.         @Override 
  4.         public void callMethodInService() { 
  5.  
  6. //实现方法 
  7.             sayHello(); 
  8.  
  9.         } 
  10.  
  11.     } 
  12.  
  13.  
  14.     public void sayHello(){ 
  15.  
  16.         System.out.print("I am working in service"); 
  17.         Log.i("ss", "I am working in service"); 
  18.     } 

 

No3.在相应Service的onBind方法中返回在No2.定义的MyBinder类的一个对象

 

    
    
    
    
  1. @Override 
  2.     public IBinder onBind(Intent intent) { 
  3.         // TODO Auto-generated method stub 
  4.         return new MyBinder(); 
  5.     } 

 

No4.绑定Service的时候,用的方法是

Intent intent = new Intent(Serivcet_MainActivity.this, MyService.class);

bindService(intent, conn, Service.BIND_AUTO_CREATE);

 其中的conn就是一个ServiceConnection对象,在ServiceConnection中有两个方法:

onServiceConnected(ComponentName name, IBinder service)绑定服务成功后回调

onServiceDisconnected(ComponentName name)取消绑定服务后回调

onServiceConnected(ComponentName name, IBinder service)方法中的IBinder service就是在Service中的onBind()方法中返回的MyBinder对象。

你会感到疑惑了?

我们在Service 中的onBind()方法返回的是一个MyBinder对象,这个MyBinder类继承自Binder类,而这里的IBinder Service是一个IBinder对象,去查一下API

关于IBinder

 

 

明白了吧!IBinder是一个接口,而Binder是它的实现类。这里利用的是java的多态特性,我们只需要拿到这个IBinder对象 ,进行强转到IService就可以了。具体实现如下

 

     
     
     
     
  1. ServiceConnection conn = new ServiceConnection() { 
  2.  
  3.             @Override 
  4.             public void onServiceDisconnected(ComponentName name) { 
  5.                 myBinder = null
  6.             } 
  7.  
  8.             @Override 
  9.             public void onServiceConnected(ComponentName name, IBinder service) { 
  10.                 myBinder = (IService) service; 
  11.  
  12.             } 
  13.         }; 

 

NO5.好了,拿到这个返回的Iservice对象就可以调用它的方法了:

myBinder.callMethodInService();

 

 

3.如何实现以及使用AIDL

 

一、首先在Server端定义AIDL文件

 

 

AIDL中的文件内容如下;

 

      
      
      
      
  1. interface IService { 
  2.  void callMethodInService(); 
  3.  void  callMethodTwo(); 

--------------------------------------------------------割线------------------------------------------------------

可以看到ADIL 就是一个接口文件,只是这个接口文件的后缀是.aidl ,并且没有任何修饰符。所以我们在创建AIDL的时候可以县创建一个普通的接口,然后将各个修饰符去掉,最后再将后缀改为.aidl

定义好Server的AIDL文件后,会发现在gen文件夹下自动生成了一个文件

打开看一下其中的内容:(内容太多,只截取其中一段)

 

       
       
       
       
  1. public interface IService extends android.os.IInterface 
  2.     /** Local-side IPC implementation stub class. */ 
  3.     public static abstract class Stub extends android.os.Binder implements cn.itcast.remoteservice.IService 
  4.  
  5.     //需要注意的就是这个Stub对象,我们可以看到他一个抽象类,继承了Binder对象,并实现了IService接口,这个接口其实就是我们定义的Server端的AIDL文件。 
  6.     { 
  7.         private static final java.lang.String DESCRIPTOR = "cn.itcast.remoteservice.IService"
  8.         /** Construct the stub at attach it to the interface. */ 
  9.         public Stub() 
  10.         { 
  11.             this.attachInterface(this, DESCRIPTOR); 
  12.         } 
  13.         /** 
  14.          * Cast an IBinder object into an cn.itcast.remoteservice.IService interface, 
  15.          * generating a proxy if needed. 
  16.          */ 
  17.         Public static  
  18.         cn.itcast.remoteservice.IService asInterface(android.os.IBinder obj) 
  19.         //这个方法需要注意一下,方法名字是  asInterface(IBinder binder),返回类型是   IService 
  20.         { 
  21.             if ((obj==null)) { 
  22.                 return null; 
  23.             } 
  24.             android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR); 
  25.             if (((iin!=null)&&(iin instanceof cn.itcast.remoteservice.IService))) { 
  26.                 //返回类型都进行了强转IService类型 
  27.                 return ((cn.itcast.remoteservice.IService)iin); 
  28.             } 
  29.             //返回类型都进行了强转IService类型 
  30.  
  31.             return new cn.itcast.remoteservice.IService.Stub.Proxy(obj); 
  32.         } 
  33.         @Override public android.os.IBinder asBinder() 
  34.         { 
  35.             return this; 
  36.         } 

二、在Server定义需要被调用的Service

这里也定义了一个MyBinder类,这个类直接继承自IService中的Stub类,IService.java前面已经讲过是添加aidl后Eclipse给自动生成了。这个Stub类也讲过,是一个抽象类,继承自Binder类并实现了IService接口

所以要在MyBinder中实现AIDL中定义的方法,并在onBind()方法中返回一个MyBinder类的实例(其实这个操作和之前通过onBinder返回Binder对象,然后调用本地Service中方法差不多)

客户端在拿到这个MyBinder的实例,就可以调用 MyBinder类中实现的方法了

 

        
        
        
        
  1. public class RemoteService extends Service { 
  2.  
  3.     @Override 
  4.     public IBinder onBind(Intent intent) { 
  5.          
  6.         return new MyBinder(); 
  7.     } 
  8.     private class MyBinder extends IService.Stub{ 
  9.  
  10.  
  11.  
  12.  
  13.         @Override 
  14.         public void callMethodInService() throws RemoteException { 
  15.             sayHelloInService(); 
  16.              
  17.         } 
  18.         @Override 
  19.         public void callMethodTwo() throws RemoteException { 
  20.              
  21.         } 
  22.          
  23.     }     
  24.     public void sayHelloInService(){ 
  25.         System.out.println("hello in service"); 
  26.     } 
  27.      
  28.     @Override 
  29.     public void onCreate() { 
  30.         System.out.println("remote service oncreate"); 
  31.         super.onCreate(); 
  32.     } 
  33.  

三、Client端添加AIDL文件

将Server端的AIDL文件拷贝到Client端工程中,注意包名、AIDL文件名必须一样

 

四、在Client端调用Server中Service方法

NO1.在调用之前首先应该在bind服务的时候获取Server端Service的OnBind() 方法里面返回的那个MyBinder实例,和bind本地服务一样,同样是在ServiceConnection的onServiceConnected(ComponentName name, IBinder service)方法中,将IBinder Service对象进行强转,只不过,这次强转为AIDL的类型也就是IService类型,这个强转有现成的方法:

就是IService.Stub.asInterface(service);这个方法在IServer.java 文件中我们提到过,他的作用就是强转为IService类型。

 

         
         
         
         
  1. Intent intent = new Intent(); 
  2.         intent.setAction("cn.itcast.remoteservice"); 
  3.         bindService(intent, new ServiceConnection() { 
  4.              
  5.             @Override 
  6.             public void onServiceDisconnected(ComponentName name) { 
  7.                  
  8.                 //取消bind后回调的方法 
  9.                  
  10.             } 
  11.              
  12.             @Override 
  13.             public void onServiceConnected(ComponentName name, IBinder service) { 
  14.   //bind服务后回调的方法 
  15.   //通过调用Stub的asInterface将传入的service对象,强转为AIDL定义的接口类型,这里定义的是IService类型。 
  16.                 iService = IService.Stub.asInterface(service); 
  17.                  
  18.             } 
  19.         }, BIND_AUTO_CREATE); 

NO2.好了我们终于在Client端中拿到了这个IService对象,然后直接调用方法吧。

 

          
          
          
          
  1. // 调用了远程服务的方法  
  2. iService.callMethodInService();//方法一 
  3. iService.callMethodTwo();//方法二 

 

 

 

 

 

 

 

你可能感兴趣的:(android,aidl,AIDL学习)