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

}
时间: 2024-11-09 21:11:31

Android Studio创建AIDL文件并实现进程间通讯的相关文章

Android中的AIDL Android studio中建aidl

1.aidl: android interface definition language,是一种它是一种android内部进程通信接口的描述语言,通过它我们可以定义进程间的通信接口icp:interprocess communication :内部进程通信 2.既然aidl可以定义并实现进程通信,那么我们怎么使用它呢?文档/android-sdk/docs/guide/developing/tools/aidl.html中对步骤作了详细描述: --1.Create your .aidl fil

Android AIDL 进行进程间通讯(IPC)

编写AIDL文件时,需要注意: 1.接口名和aidl文件名相同. 2.接口和方法前不用加访问权限修饰符 (public.private.protected等,也不能用final.static). 3.AIDL默认支持的类型包括java基本类型 (int.long.boolean等) 和 (String.List.Map.CharSequence),使用这些类型时不需要import声明.对于List和Map中的元素类型必须是AIDL支持的类型,如果使用自定义类型作为参数或者返回值,自定义类型必须实

Android进阶笔记04:Android进程间通讯之Messenger ( 区别于AIDL)

一. Android进程间通讯之Messenger 的引入 (1)引言:      平时一说进程间通讯,大家都会想到AIDL,其实messenger和AIDL作用一样,都可以进行进程间通讯.它是基于消息的进程间通信,就像子线程和UI线程发送消息那样,是不是很简单,还不用去写AIDL文件,是不是有点小爽.哈哈.此外,还支持记录客户端对象的Messenger,然后可以实现一对多的通信:甚至作为一个转接处,任意两个进程都能通过服务端进行通信. (2) Messenger 与 AIDL 比较:    

Android Studio创建Android Library发布至本地仓库

本文通过Android Studio创建一个Android Library项目,然后发布到本地的Maven仓库. 1.创建Android Library模块 2.配置build.gradle apply plugin: 'com.android.library' apply plugin: 'maven' android {     compileSdkVersion 21     buildToolsVersion "21.1.2"     defaultConfig {      

Android Studio创建项目

创建项目 首先,先指出Android Studio中的两个概念. Project 和 Module .在Android Studio中, Project 的真实含义是工作空间, Module 为一个具体的项目. 在 Eclipse 中,我们可以同时对多个 Eclipse 的 Project 进行同时编辑,这些 Project 在同一个 workspace 之中.在Android Studio中,我们可以同时对多个Android Studio的 Module 进行同时编辑,这些 Module 在同

android studio创建模拟器报错解决 emulator: ERROR: This AVD&#39;s configuration is missing a kernel file!!

android studio创建模拟器报错 emulator: ERROR: This AVD's configuration is missing a kernel file!! 的解决办法 原因有二:1 没有,解决办法通过sdk mangager 下载 2 找不到,解决办法看系统环境变量path(此种情况多数发生在android Studio和EclipseADT同时存在的情况下) 原因是在刚刚安装完毕的androidstudio的sdk目录下没有system-image目录,也许有但没有相

Android Studio创建库项目及引用

Android Studio创建库项目其实创建的是在主项目下创建Module模块,这个Module模块创建的时候选择库项目模式. 为什么要这样处理呢?因为在Android Studio中一个WorkSpace工作空间就是一个Android主项目.主项目其实也就是这个工作空间的一个Module模块,只不过这个模块是一个主模块.如果要想创建库项目,显而易见也应该是一个module模块项目,设置成Library就可以了. 然后自动生成的build.gradle文件里面会有一行标示 apply plug

用android studio创建第一个安卓程序加载html5 页面

前言 软件版本:android studio v1.0正式版,由于v0.x以来软件变化一直比较大,很多问题搜索的解决方案也都是v0.x版本时代的,故首先声明一下版本. 动机:由于工作中需要对移动端软件开发的几种方式进行一下对比研究,故有了此文章的产生,估计后续还会有其他技术方案的文章发布. 目标:为了适应跨平台的要求,所以用html5编写页面,利用webview装载html5页面就成为了一个备选的技术路线.本篇文章就是利用android studio创建一个apk程序,装载编写好的html5页面

使用Android Studio创建Android项目

创建项目 首先,在Android Studio中: Project 和 Module, Project 的真实含义是工作空间, Module 为一个具体的项目. 在 Eclipse 中,可以同时对多个 Eclipse 的 Project 进行同时编辑,这些 Project 在同一个 workspace 之中.在Android Studio中,我们可以同时对多个Android Studio的 Module 进行同时编辑,这些 Module 在同一个 Project 之中. Eclipse 的 Pr