栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 移动开发 > Android

实例讲解Android中的AIDL内部进程通信接口使用

Android 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

实例讲解Android中的AIDL内部进程通信接口使用

首先描述下我们想要实现的内容,我们希望在一个应用中通过点击按钮,去操作另一个进程中应用的音乐播放功能。

如图,我们点击“播放”时,系统就会去远程调用我们提供的一个service(与当前service不是同一个应用哦),然后操作service中的音乐播放,点击“停止”则会终止播放。想要重新播放的话,必须先点“销毁service”,再点播放按钮哦。(至于这里为什么要先点销毁按钮才能播放,完全是为了给大家展示下,远程调用service时,怎么去解绑service)。

在这个例子中,我们用到了一个非常重要的概念,AIDL。

AIDL(android interface definition language)android接口描述语言,其主要的作用就是允许我们在不同的进程间进行通信。

      我们都知道每个应用程序都运行在各自的进程中,并且android平台是不允许不同进程间进行直接的对象数据等传递的。如果我们非要进行进程间的通讯,那么我们就必须将我们的数据对象分解成一个个微小的、可以被操作系统理解的数据单元,然后有序的通过进程边界的检查。

      如果让我们自己实现,那么这个过程都愁死一批批的程序人了。幸好android,为我们解决了这个问题,这就是AIDL出现的原因了。

      AIDL (Android Interface Definition Language)是一种IDL 语言,用于生成可以在Android设备上两个进程之间进行进程间通信(IPC)的代码。如果在一个进程中(例如Activity)要调用另一个进程中(例如Service)对象的操作,就可以使用AIDL生成可序列化的参数。
AIDL IPC机制是面向接口的,像COM或Corba一样,但是更加轻量级。它是使用代理类在客户端和实现端传递数据。

 

     注意:AIDL只支持方法,不能定义静态成员,并且方法也不能有类似public等的修饰符;AIDL运行方法有任何类型的参数和返回值,在java的类型中,以下的类型使用时不需要导入包(import),基本数据类型、String、Map、List.当然为了避免出错,建议只要使用了,就导入包。
     
使用AIDL的步骤:

服务端(提供服务):

第一步:定义一个*.aidl文件,该文件里是符合aidl语言规范的接口定义,里面定义了外部应用可以访问的方法。当我们保存该文件的时候,eclipse会自动为我们在gen文件夹下生成一个相应的java接口文件。例如RemoteServiceInterface.java

 第二步:定义一个自己的service,    并将其注册到androidManifest.xml文件中,例如:


 
 
 
 

注意这里一定要提供一个intent-filter,我们的客户端进程就是通过该action访问到服务端进程的哦。

我们都知道,在实现自己的service时,为了其他应用可以通过bindService来和我们的service进行交互,我们都要实现service中的onBind()方法,并且返回一个继承了Binder的内部类;在这里,eclipse自动为我们生成的RemoteServiceInterface.java中有一个实现了Binder的内部类,RemoteServiceInterface.Stub。AIDL要求我们,在这里不能再直接去实现Binder类了,而是去实现,AIDL提供给我们的Stub类。 实现stub类的同时,AIDL还要求我们同时实现我们在接口中定义的各种服务的具体实现。至此为止,我们的服务端已经和我们的aidl文件绑定到一起了哦。

客户端:

第一步:客户端要想使用该服务,肯定要先知道我们的服务在aidl文件中到底对外提供了什么服务,对吧?所以,第一步,我们要做的就是,将aidl文件拷贝一份到客户端的程序中(这里一定要注意,包路径要和服务端的保持一致哦,例如服务端为cn.com.chenzheng_java.remote.a.aidl,那么在客户端这边也应该是这个路径)。

第二步:我们都知道,想要和service交互,我们要通过bindService方法,该方法中有一个ServiceConnection类型的参数。而我们的主要代码便是在该接口的实现中。

第三步:在ServiceConnection实现类的onServiceConnected(ComponentName name, IBinder service)方法中通过类似remoteServiceInterface = RemoteServiceInterface.Stub.asInterface(service);方式就可以获得远程服务端提供的服务的实例,然后我们就可以通过remoteServiceInterface 对象调用接口中提供的方法进行交互了。(这里的关键是通过*.Stub.asInterface(service);方法获取一个aidl接口的实例哦)

我们前面在服务端中说过了,必须提供一个intent-filter来匹配请求是否合法,所以我们在客户端访问服务的时候,还必须传递包含了匹配action的Intent哦。

下边整体是代码:
 远程服务端:

RemoteServiceInterface.aidl

package cn.com.chenzheng_java.remote; 
 
 
 
 interface RemoteServiceInterface { 
 
   void startMusic(); 
   void stopMusic(); 
} 

MyRemoteService.java

package cn.com.chenzheng_java.remote; 
 
import java.io.IOException; 
 
import android.app.Service; 
import android.content.Intent; 
import android.media.MediaPlayer; 
import android.os.IBinder; 
import android.os.RemoteException; 
 
public class MyRemoteService extends Service { 
  MediaPlayer mediaPlayer; 
  @Override 
  public IBinder onBind(Intent intent) { 
    return new MyBinder(); 
  } 
  @Override 
  public void onCreate() { 
     
     mediaPlayer = MediaPlayer.create(MyRemoteService.this, R.raw.aiweier); 
    super.onCreate(); 
  } 
   
   
  private class MyBinder extends RemoteServiceInterface.Stub{ 
 
    public void startMusic() throws RemoteException { 

mediaPlayer.start(); 

    } 
 
    public void stopMusic() throws RemoteException { 
      mediaPlayer.stop(); 
      try { 
 mediaPlayer.prepare(); 
      } catch (IllegalStateException e) { 
 e.printStackTrace(); 
      } catch (IOException e) { 
 e.printStackTrace(); 
      } 
    } 
     
  } 
 
} 

RemoteServiceActivity.java

package cn.com.chenzheng_java.remote; 
 
import android.app.Activity; 
import android.os.Bundle; 
 
public class RemoteServiceActivity extends Activity { 
  @Override 
  public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.main); 
  } 
} 

androidManifest.xml

 
 
   
 
   
     
       
  
  
       
     
     
   
     
     
     
   
 
   
 

客户端:

activity代码:

package cn.com.chenzheng_java; 
 
import android.app.Activity; 
import android.content.ComponentName; 
import android.content.Context; 
import android.content.Intent; 
import android.content.ServiceConnection; 
import android.os.Bundle; 
import android.os.IBinder; 
import android.os.RemoteException; 
import android.util.Log; 
import android.view.View; 
import android.view.View.OnClickListener; 
import android.widget.Button; 
import cn.com.chenzheng_java.remote.RemoteServiceInterface; 
 
public class LocalServiceActivity extends Activity implements onClickListener { 
  String ACTION_NAME = "cn.com.chenzheng_java.remote"; 
  boolean flag = false; 
  Button button_start ; 
  Button button_stop ; 
  Button button_destroy ; 
   
  @Override 
  public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.music); 
     
    button_start = (Button) findViewById(R.id.button1); 
    button_stop = (Button) findViewById(R.id.button2); 
    button_destroy = (Button) findViewById(R.id.button3); 
     
    button_start.setonClickListener(this); 
    button_stop.setonClickListener(this); 
    button_destroy.setonClickListener(this); 
  } 
 
  RemoteServiceInterface remoteServiceInterface ; 
   
  private class MyServiceConnection implements ServiceConnection{ 
    public void onServiceConnected(ComponentName name, IBinder service) { 
      remoteServiceInterface = RemoteServiceInterface.Stub.asInterface(service); 
      try { 
 Log.i("flag", flag+""); 
 if(flag){ 
   Log.i("通知", "已经开始唱歌"); 
   remoteServiceInterface.startMusic(); 
 }else{ 
   Log.i("通知", "已经停止唱歌"); 
   remoteServiceInterface.stopMusic(); 
 } 
  
  
      } catch (RemoteException e) { 
 e.printStackTrace(); 
      } 

    } 
 
    public void onServiceDisconnected(ComponentName name) { 

    } 
     
  } 
   
  private MyServiceConnection serviceConnection = new MyServiceConnection(); 
   
  public void onClick(View v) { 
    if(v == button_start){ 
      flag = true; 
      Intent intent = new Intent(ACTION_NAME); 
       
      bindService(intent, serviceConnection ,Context.BIND_AUTO_CREATE); 
    } 
     
    if(v == button_stop){ 
      Log.i("通知", "已经点击了停止按钮"); 
      flag = false; 
      Intent intent = new Intent(ACTION_NAME); 
      bindService(intent, serviceConnection ,Context.BIND_AUTO_CREATE); 
      try { 
 remoteServiceInterface.stopMusic(); 
      } catch (RemoteException e) { 
 e.printStackTrace(); 
      } 
    } 
     
    if(v == button_destroy){ 
      flag = false; 
      Intent intent = new Intent(ACTION_NAME); 
      bindService(intent, serviceConnection ,Context.BIND_AUTO_CREATE); 
      unbindService(serviceConnection); 
    } 
     
  } 
} 

music.xml

 
 
   
   
   
 


其他没有粘贴出来的代码都是由系统默认生成的。

AIDL与传递对象

除了上面我们提到的通过service提供音乐播放等类似的服务之外,我们还可以通过service将对象传递回来哦,你知道怎么用吗,先看例子:

当我们点击“获取”时,会从另一个线程的service中获取一个对象,然后将里面的内容读出来。

对于aidl实现以对象的方式交互。主要步骤如下:

服务端:
第一:定义一个实体类,这里是Beauty,定义一个服务接口aidl文件RemoteBeauty.aidl,这里有一点需要注意,我们引用自定义的实体类到aidl中时需要通过import导入包,但是你会发现,即使你导入了包,还是提示找不到,这时候,你要做的是,建一个以实体类名称命名的aidl文件,如Beauty.aidl,在里面添加一句pracelable Beauty。

第二:开始编写Beauty,这里一定要注意,它一定要实现Pracelable接口,该接口是一个序列化的接口,功能和serializable相似,但是功能更加的迅速。此外,在该Beauty内部一定要声明一个public static final Pracelable.CreatorCREATOR对象!!除了里面的那个T代表实体类之外,其他的都不准改变哦。

第三:在androidManifest.xml中注册service。并定义好访问该service的action字符串。

客户端:
客户端这边相应的要简单很多,但是要注意的一点是,要将实体类还有aidl文件都拷贝过来哦,而且要保证路径完全一致!!

Beauty.java

package cn.com.chenzheng_java.service; 
 
import android.os.Parcel; 
import android.os.Parcelable; 
 
public class Beauty implements Parcelable { 
 
  String name ; 
  int age ; 
  String sex ; 
   
  public String getName() { 
    return name; 
  } 
 
  public void setName(String name) { 
    this.name = name; 
  } 
 
  public int getAge() { 
    return age; 
  } 
 
  public void setAge(int age) { 
    this.age = age; 
  } 
 
  public String getSex() { 
    return sex; 
  } 
 
  public void setSex(String sex) { 
    this.sex = sex; 
  } 
 
  @Override 
  public int describeContents() { 
    return 0; 
  } 
 
   
  @Override 
  public void writeToParcel(Parcel dest, int flags) { 

      dest.writeString(name); 
      dest.writeInt(age); 
      dest.writeString(sex); 
  } 
   
  public static final Parcelable.Creator CREATOR = new Creator() { 
     
     
    @Override 
    public Beauty[] newArray(int size) { 
      return new Beauty[size]; 
    } 
     
     
    @Override 
    public Beauty createFromParcel(Parcel source) { 
      String name = source.readString(); 
      int age = source.readInt(); 
      String sex = source.readString(); 
      Beauty beauty = new Beauty(); 
      beauty.setName(name); 
      beauty.setAge(age); 
      beauty.setSex(sex); 

      return beauty; 
    } 
  };    
   
} 

RemoteService.java

package cn.com.chenzheng_java.service; 
 
import android.app.Service; 
import android.content.Intent; 
import android.os.IBinder; 
import android.os.RemoteException; 
import android.util.Log; 
 
public class RemoteService extends Service { 
 
  @Override 
  public IBinder onBind(Intent intent) { 
    Log.i("通知", "执行了OnBind"); 
    return new MyBinder(); 
  } 
 
   
  private class MyBinder extends RemoteBeauty.Stub{ 
 
    @Override 
    public Beauty getBeauty() throws RemoteException { 

      Beauty beauty = new Beauty(); 
      beauty.setName("feifei"); 
      beauty.setAge(21); 
      beauty.setSex("female"); 

      return beauty; 
    }} 
   
   
   
} 

ServiceActivity.java

package cn.com.chenzheng_java.service; 
 
import android.app.Activity; 
import android.os.Bundle; 
 
public class ServiceActivity extends Activity { 
  @Override 
  public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.main); 
  } 
} 

Beauty.aidl

parcelable Beauty; 

RemoteBeauty.aidl

package cn.com.chenzheng_java.service; 
import cn.com.chenzheng_java.service.Beauty; 
 interface RemoteBeauty { 
 
  Beauty getBeauty(); 
   
} 

manifest.xml

 
 
   
 
   
     
       
  
  
       
     
 
 
   
     

     
   
 
   
 

客户端:

ClientActivity.java

package cn.com.chenzheng_java.client; 
 
import android.app.Activity; 
import android.content.ComponentName; 
import android.content.Context; 
import android.content.Intent; 
import android.content.ServiceConnection; 
import android.os.Bundle; 
import android.os.IBinder; 
import android.os.RemoteException; 
import android.util.Log; 
import android.view.View; 
import android.view.View.OnClickListener; 
import android.widget.Button; 
import android.widget.TextView; 
import cn.com.chenzheng_java.service.Beauty; 
import cn.com.chenzheng_java.service.RemoteBeauty; 
 
public class ClientActivity extends Activity implements onClickListener { 
  TextView textView ; 
  Button button ; 
  String actionName = "cn.com.chenzheng_java.remote2"; 
  RemoteBeauty remoteBeauty; 
   
  @Override 
  public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.main); 
    textView = (TextView) findViewById(R.id.textView1); 
    button = (Button) findViewById(R.id.button1); 
     
    button.setonClickListener(this); 
  } 
 
  private class MyServiceConnection implements ServiceConnection{ 
 
    @Override 
    public void onServiceConnected(ComponentName name, IBinder service) { 
      Log.i("通知", "链接成功!"); 
      remoteBeauty = RemoteBeauty.Stub.asInterface(service); 
      try { 
 Beauty beauty = remoteBeauty.getBeauty(); 
 textView.setText("美女 姓名:"+beauty.getName()+" 年龄:"+beauty.getAge() +" 性别:"+beauty.getSex()); 
  
  
      } catch (RemoteException e) { 
 e.printStackTrace(); 
      } 
    } 
 
    @Override 
    public void onServiceDisconnected(ComponentName name) { 

    } 
     
  } 
  MyServiceConnection connection = new MyServiceConnection(); 
  @Override 
  public void onClick(View v) { 
    Intent intent = new Intent(actionName); 
    bindService(intent, connection, Context.BIND_AUTO_CREATE); 
  } 
} 

另外Beauty.java 以及RemoteBeauty.aidl都是从服务端系统中拷贝过来的哦。

如果你想你的service在系统开机时自启动。可以在service的androidManifest.xml中加上这样的配置。

 

      

  

          



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/162820.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号