Android Studio创建AIDL文件并实现进程间通讯实例

在Android系统中,跨进程通信是非常普遍的事情,它用到了Binder机制处理进程之间的交互。Binder机制会开放一些接口给Java层,供android开发工程师调用进程之间通信。这些接口android封装到了AIDL文件里,当我们项目用到跨进程通信时可以创建.aidl文件,.aidl文件可以协助我们达到跨进程的通信。下面简单介绍用AndroidStudio创建AIDL文件的过程。

a.新建AIDL文件

1.项目文件夹右键---> new --->选择AIDL

2.自定义一个接口名称

3.创建之后我们看到了xxx.aidl文件,然后编辑自己项目需要实现的方法,这里很简单就获取一个字符串的方法getAllName。

4.写好之后,我们需要重新ReBuild,完后在项目build/generated/source/aidl/debug/包名 目录下就看到了系统为我们生成的以刚才.aidl文件名命名的java文件。

该java文件系统会自动生成代码:

Stub:描述了一个Java服务,对应是一个远程的Service。

Proxy:描述了一个Java服务的代理对象,在Client端就会得到这个对象。

这两者都实现了IPersonManager接口。

asInterface:将Java服务的代理对象即一个BinderProxy封装成了一个IPersonManager.Stub.Proxy对象,实现了IPersonManager接口。

onTransact:负责接收分发进程间的通信。它首先会收到Client发来的请求,不同的方法进入相应的case代码中,然后交给Stub的子类去处理事件,例如 java.lang.String _result = this.getAllName();   这里的this就可以让它的子类去接收该请求并处理。
IBinder的transact方法:用来发送进程间的请求。

b.利用AIDL实现进程间的通讯

一:接口文件中只含有基础数据类型

如上aidl文件,IPersonManager中只用到了基本数据类型,此时要完善Server端的小项目,还需要新建一个Service。
Server端代码如下

public class PersonService extends Service { 

  private static String names = "alice & iland";
  public PersonBinder mPersonBinder;
  @Override
  public void onCreate() {
    super.onCreate();
    mPersonBinder = new PersonBinder();
  } 

  @Override
  public IBinder onBind(Intent intent) {
    return mPersonBinder;
  }
  public class PersonBinder extends IPersonManager.Stub{ 

    @Override
    public String getAllName() throws RemoteException {
      return names;
    }
  } 

}

继承系统的Service,并建立一个内部类继承IPersonManager.Stub,这里很简单,当客户端请求要获取名字时我们这里把names给到客户端。

Client端代码如下

public class MainActivity extends AppCompatActivity implements View.OnClickListener{
  private static final String TAG = "MainActivity";
  private Button btnGet;
  private EditText etShow;
  public IPersonManager mIPersonManager;
  ServiceConnection sc = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
      Log.i(TAG, "onServiceConnected: ");
      mIPersonManager = IPersonManager.Stub.asInterface(service);
    } 

    @Override
    public void onServiceDisconnected(ComponentName name) {
      Log.i(TAG, "onServiceDisconnected: ");
      mIPersonManager = null;
    }
  };
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    btnGet = (Button) findViewById(R.id.btn_getname);
    etShow = (EditText) findViewById(R.id.et_allnamef);
    btnGet.setOnClickListener(this); 

    Intent intent = new Intent("com.ly.testaidlserver.aidl.AIDL_SERVICE");
    intent.setPackage("com.ly.testaidlserver");
    bindService(intent,sc, Service.BIND_AUTO_CREATE);
  } 

  @Override
  public void onClick(View v) {
    switch (v.getId()){
      case R.id.btn_getname:
        String names = null;
        try {
          if (mIPersonManager!=null)
            names = mIPersonManager.getAllName();
        } catch (RemoteException e) {
          e.printStackTrace();
        }
        etShow.setText(names);
        break;
      default:
        break;
    }
  }@Override
  protected void onDestroy() {
    super.onDestroy();
    unbindService(sc);
  } 

}

在onServiceConnected方法中拿到IPersonManager的代理对象,最终获取到 alice & ilan,与服务端数据一致。

注意:

1.bindService方法在5.0以后做出改变,隐式意图需要设置Package 或者 Commponent,直接定义一个action是报异常的。

Intent intent = new Intent("com.ly.testaidlserver.aidl.AIDL_SERVICE");
intent.setPackage("com.ly.testaidlserver");
bindService(intent,sc, Service.BIND_AUTO_CREATE); 

2.我们需要把Server端的aidl文件复制到Client端,在Client中存放aidl的文件夹也需要跟Server端包名一致。

如图:

上图为aidl文件在Server端存放的路径,下图为复制到Client端aidl文件的路径,这里要保持一致,因此Client端需要针对Server端的包名新建一个Package。

3.当我们启动项目的时候,如果在Activity中IPersonManager找不到报出异常,请在app的build.gradle中添加aidl文件指名目录,如本例中添加,

  sourceSets{
    main {
      aidl.srcDirs = ['src/main/aidl','src/main/java']
    }
  }

二:接口文件中含有复杂数据类型、

1.新建一个Person.aidl     内容非常简单
parcelable Person;

2.新建一个Person实体类,为了能在进程间进行通信必须实现Parcelable接口。

3.在IPersonManager中添加了一个方法,这里注意用到的Person类必须将包名improt进去。

4.将IPersonManager.aidl、Person.aidl、Person.java复制到客户端的aidl包下。

5.查看是否需要修改build.gradle中sourceSets设置

代码基本没有变化:

Person.java

public class Person implements Parcelable {
  String name;
  int age; 

  public Person(String name, int age) {
    this.name = name;
    this.age = age;
  } 

  public static final Creator<Person> CREATOR = new Creator<Person>() {
    @Override
    public Person createFromParcel(Parcel in) {
      return new Person(in.readString(), in.readInt());
    } 

    @Override
    public Person[] newArray(int size) {
      return new Person[size];
    }
  }; 

  @Override
  public int describeContents() {
    return 0;
  } 

  @Override
  public void writeToParcel(Parcel dest, int flags) {
    dest.writeString(name);
    dest.writeInt(age);
  } 

  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;
  }
}

IPersonManager.aidl

interface IPersonManager {
  String getAllName();
  List<Person> getPersonList();
} 

Server

public class PersonService extends Service { 

  private List<Person> persons = new ArrayList<Person>();
  public PersonBinder mPersonBinder;
  @Override
  public void onCreate() {
    super.onCreate();
    mPersonBinder = new PersonBinder();
    Person p1 = new Person("alice",23);
    persons.add(p1);
    Person p2 = new Person("iland",18);
    persons.add(p2);
  } 

  @Override
  public IBinder onBind(Intent intent) {
    return mPersonBinder;
  }
  public class PersonBinder extends IPersonManager.Stub{ 

    @Override
    public String getAllName() throws RemoteException {
      return "";
    } 

    @Override
    public List<Person> getPersonList() throws RemoteException {
      return persons;
    }
  }
}

Clent

public class MainActivity extends AppCompatActivity implements View.OnClickListener{
  private static final String TAG = "MainActivity";
  private Button btnGet;
  private EditText etShow;
  public IPersonManager mIPersonManager;
  ServiceConnection sc = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
      Log.i(TAG, "onServiceConnected: ");
      mIPersonManager = IPersonManager.Stub.asInterface(service);
    } 

    @Override
    public void onServiceDisconnected(ComponentName name) {
      Log.i(TAG, "onServiceDisconnected: ");
      mIPersonManager = null;
    }
  };
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    btnGet = (Button) findViewById(R.id.btn_getname);
    etShow = (EditText) findViewById(R.id.et_allnamef);
    btnGet.setOnClickListener(this); 

    Intent intent = new Intent("com.ly.testaidlserver.aidl.AIDL_SERVICE");
    intent.setPackage("com.ly.testaidlserver");
    bindService(intent,sc, Service.BIND_AUTO_CREATE);
  } 

  @Override
  public void onClick(View v) {
    switch (v.getId()){
      case R.id.btn_getname:
        ArrayList<Person> persons = null;
        try {
          if (mIPersonManager!=null)
            persons = (ArrayList<Person>) mIPersonManager.getPersonList();
        } catch (RemoteException e) {
          e.printStackTrace();
        }
        String result = "";
        for (Person person : persons){
          result = result+person.getName()+"__"+person.getAge();
        }
        etShow.setText(result);
        break;
      default:
        break;
    }
  }@Override
  protected void onDestroy() {
    super.onDestroy();
    unbindService(sc);
  } 

}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 使用Android studio创建的AIDL编译时找不到自定义类的解决办法

    使用AS创建ADIL文件时AS会在main文件夹下给我们生成一个aidl文件夹和一个相同包名的包,通常我们会把所有和ADIL相关的类或文件放在这个包下,但是如果存在自定义的类时,程序编译时无法通过,提示找不到自定义的包.解决办法如下,在启动Module的build.gradle中加入如下代码: sourceSets { main { manifest.srcFile 'src/main/AndroidManifest.xml' java.srcDirs = ['src/main/java', '

  • Android Studio 引入 aidl 文件的方法汇总

    AndroidStudio 引入 aidl 文件,一般来说,有两种方法. 第一种方法 直接在 src/main 目录下新建 aidl 文件夹,并将我们的 aidl 文件放到该目录下.因为 AndroidStudio 默认的 aidl 文件默认配置是这样的. 第二种方法 把 adil 文件拷贝到libs文件夹下在build.gradle文件中配置 sourceSets { main { jniLibs.srcDirs = ['libs'] aidl.srcDirs = ['src/main/jav

  • Android IPC进程间通信详解最新AndroidStudio的AIDL操作)

    前言 前面梳理了Android的线程间的通信<Thread.Handler和HandlerThread关系何在?> ,这些都是在同一个进程中,那进程间的通信,或者说不同的应用间的通信该如何实现呢?这个时候就要用到AIDL(Android Interface Definition LanguageAndroid接口定义语言 ). 使用方法(AndroidStudio) 我发现现在AIDL的教程基本上还是eclipse的,但是在AndroidStudio里面使用AIDL还是有一些不同的,来看看怎么

  • Android Studio创建AIDL文件并实现进程间通讯实例

    在Android系统中,跨进程通信是非常普遍的事情,它用到了Binder机制处理进程之间的交互.Binder机制会开放一些接口给Java层,供android开发工程师调用进程之间通信.这些接口android封装到了AIDL文件里,当我们项目用到跨进程通信时可以创建.aidl文件,.aidl文件可以协助我们达到跨进程的通信.下面简单介绍用AndroidStudio创建AIDL文件的过程. a.新建AIDL文件 1.项目文件夹右键---> new --->选择AIDL 2.自定义一个接口名称 3.

  • Android Studio编写AIDL文件后如何实现自动编译生成

    在目录src/main 下新建了aidl 文件夹之后,在aidl文件夹中也创建了相同的包路径, 创建AIDL文件 XXX.aidl 如果XXX.aidl引用了一个java下的model例如引用了a.b.c.Model; 则需要在XXX.aidl文件中声明import a.b.c.Model;全路径. 并且创建另一个文件Model.aidl 在Model.aidl文件中声明以下内容 package xxxx包名称; parcelable Model; 如果编译的时候提示AIDL文件引用的包找不到的

  • php进程间通讯实例分析

    本文实例讲述了php进程间通讯的方法.分享给大家供大家参考,具体如下: php单进程单线程处理批量任务太慢了,受不鸟了,但是php不能多线程,最终选择了多进程处理批量任务. php多进程主要使用for进行分裂,然后利用的unix/linux的信号量进行进程间通讯. 本例使用的是:生产者=>消费者=>收集器,的模式. <?php // ===== 全局变量 ===== // ipc进程间通讯 $key = ftok(__FILE__, "a"); $queue = ms

  • Android 创建AIDL文件使用教程

    目录 前言 1 创建 AIDL 文件 2 实现接口 3 服务端公开接口 4 客户端调用 IPC 方法 5 通过 IPC 传递对象 前言 AIDL(Android Interface Definition Language)是一种 IDL 语言,用于生成可以在 Android 设备上两个进程之间进行进程间通信(IPC)的代码. 通过 AIDL,可以在一个进程中获取另一个进程的数据和调用其暴露出来的方法,从而满足进程间通信的需求.通常,暴露方法给其他应用进行调用的应用称为服务端,调用其他应用的方法的

  • android studio创建C++项目的实现示例

    目录 一.创建Native C++工程 二.配置工程环境 三.运行代码 四.下载C++运行依赖的工具包 五.创建虚拟机 六.运行代码 问题一:如果启动虚拟机后,而左上角的虚拟机没有加载出来. 问题二:java文件无法运行,或者adb无法运行 一.创建Native C++工程 二.配置工程环境 三.运行代码 选择左上角的工程,将Android换成Project 四.下载C++运行依赖的工具包 如图所示,选择NDK和CMake,并点击Apply,此时会出现弹窗,告诉你要安装的包的名称.版本等信息,此

  • Android studio创建第一个app

    本文实例为大家介绍了Android studio创建第一个app的详细步骤,供大家参考,具体内容如下 1.创建HelloWorld项目 任何编程语言写出的第一个程序毫无疑问都会是Hello World,这已经是自20世纪70年代一直流传下来的传统,在编程界已成为永恒的经典,那么今天就来使用Android studio创建第一个app(Hello World). 首先运行Android studio,在弹出的快捷窗口中新建一个项目. 点击上面截图中的"Star a new Android Stud

  • Android Studio 中aidl的自定义类的使用详解

    自己折腾了好久,记录一下. service端: 1:创建类Dog,需要实现Parcelable接口: 2:aidl下创建 Dog.aidl,里面两句话就可以了 (1)package s包名; (2)parcelable Dog; 3:interface.aidl引入Dog类, import s包名.Dog; Client 端: 1:创建类Dog,需要实现Parcelable接口: 2:aidl下创建 Dog.aidl, (1)package c包名; (2)parcelable Dog; 注意:

  • Android Studio 创建自定义控件的方法

    我们知道,当系统控件并不能满足我们的需求时,我们就需要来创建自定义控件,主要有两种方法 (1)引入布局 下面来自定义一个控件,iPhone的标题栏,创建一个标题栏并不是什么难事,加入两个button一个TextView就行了,可是在我们的应用中,有很多页面都是需要这样的标题栏,我们不可能每个活动都写一遍布局,这个时候我们就可以用引用布局的方法,新建一个title.xml <?xml version="1.0" encoding="utf-8"?> <

随机推荐