浅谈AIDL

来源:互联网 发布:云计算 国家政策汇总 编辑:程序博客网 时间:2024/05/01 15:33

AIDL(Android接口定义语言)是为了解决进程间通信,定义两个应用程序之间的通信规则。解决进程间通信的有:service,Contentprovide,广播,Intent隐式跳转。好了,接着谈今天的

它允许您定义的编程接口,客户端和服务达成一致,以互相交流使用进程间通信(IPC)。在Android上,一个进程无法正常访问另一个进程的内存,而AIDL可以为你实现。AIDL的使用呢和我之前写的Messenger的使用有着很大的区别,我们先要搭建一个aidl服务端,搭建服务端有以下三个步骤(1)创建aidl文件,这个文件将定义方法签名的编程接口。当你构建aidl文件,Android SDK工具将自动生成一个基于内部的接口。,并将aidl文件其保存在项目的创/目录。(2)实现接口.Android SDK工具自动生成的基于aidl接口的Java编程语言接口。这个接口有一个名为stub的内在抽象类,扩展了ibinder从AIDL接口和实现方法。你必须扩展Stub类和并且实现方法。(3)公开接口给客户端。实现一个Service并覆盖onBind()返回你的stub类的实现。

服务端的配置

如果要创建一个支持绑定的service,我们必须要重写它的onBind()方法。这个方法会返回一个IBinder对象,它是客户端用来和服务器进行交互的接口。而要得到IBinder接口,我们通常有三种方式:继承Binder类,使用Messenger类,使用AIDL。

这里提出了一个IBinder接口的概念,它是一个在整个Android系统中都非常重要的东西,是为高性能而设计的轻量级远程调用机制的核心部分。当然,它不仅仅可以用于远程调用,也可以用于进程内调用——事实上,我们现在所说的service这里的IBinder既有可能出现远程调用的场景

一般来讲,我们有三种方式可以获得IBinder的对象:继承Binder类,使用Messenger类,使用AIDL。接下来我将就这三种方式展开来讲。

继承Binder类:在这里我们只需要知道,它实现了IBinder接口,通过实现Binder类,我们的客户端可以直接通过这个类调用服务端的公有方法。另外,虽然从IPC的角度来讲,Binder是Android中的一种跨进程通信方式,但是其实一般service里面的Binder是不会涉及进程间通信的

使用Messenger:大家看到Messenger可能会很轻易的联想到Message,然后很自然的进一步联想到Handler——没错,Messenger的核心其实就是Message以及Handler来进行线程间的通信

通过AIDL

AIDL,即Android Interface Definition Language,Android接口定义语言。它是一种IDL语言,可以拿来生成用于IPC的代码。基本上有下面这些步骤:

  • 服务端创建一个AIDL文件,将暴露给客户端的接口在里面声明
  • 在service中实现这些接口
  • 客户端绑定服务端,并将onServiceConnected()得到的IBinder转为AIDL生成的IInterface实例
  • 通过得到的实例调用其暴露的方法

客户端的配置

这是一种比startService更复杂的启动方式,同时使用这种方式启动的service也能完成更多的事情,比如其他组件可向其发送请求,接受来自它的响应,甚至通过它来进行IPC等等。我们通常将绑定它的组件称为客户端,而称它为服务端。
要完成客户端与服务端的绑定,有两件事要做。一是在客户端完成bindService的调用以及相关配置,二是在服务端里面实现onBind()方法的重写,返回一个用做信息交互的IBinder接口。

bindService()方法需要三个参数,第一个是一个intent,我们都很熟悉——它和startService()里面那个intent是一样的,用来指定启动哪一个service以及传递一些数据过去。第二个参数可能就有点陌生了,这是个啥?这是实现客户端与服务端通信的一个关键类。要想实现它,就必须重写两个回调方法:onServiceConnected()以及onServiceDisconnected(),而我们可以通过这两个回调方法得到服务端里面的IBinder对象,从而达到通信的目的

具体代码的实现:

//服务端

创建aidl文件,这个文件将定义方法签名的编程接口。当你构建aidl文件,Android SDK工具将自动生成一个基于内部的接口。,并将aidl文件其保存在项目的创/目录。

// IMyAidlInterface.aidlpackage com.example.administrator.my_aidl_service;// Declare any non-default types here with import statementsinterface IMyAidlInterface {    String queryNameById(int id);}
远程的服务(在其他应用程序里面的服务)

public class MyService extends Service{    private String[]names=new String[]{"xx1","xx2","xx3","xx4","xx5","xx6"};        private Mybinder mybinder=new Mybinder();    @Nullable    @Override    public IBinder onBind(Intent intent) {        return mybinder;    }    //增强版IBinder     private class Mybinder extends IMyAidlInterface.Stub{        @Override        public String queryNameById(int id) throws RemoteException {            if(id<0||id>names.length){                return "蒋总";            }else{                return names[id-1];            }        }    }}
//绑定远程服务

public class MainActivity extends AppCompatActivity {    private IMyAidlInterface asInterface;    private EditText ed_name;    private Button button_chaxun;    private TextView text_name;    //绑定一个远程服务。    private class MyServiceConnection implements ServiceConnection{        @Override        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {            Toast.makeText(MainActivity.this, "连接成功", Toast.LENGTH_SHORT).show();            asInterface = IMyAidlInterface.Stub.asInterface(iBinder);        }        @Override        public void onServiceDisconnected(ComponentName componentName) {            Toast.makeText(MainActivity.this, "连接失败", Toast.LENGTH_SHORT).show();        }    }    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        text_name = (TextView) findViewById(R.id.text_name);        ed_name = (EditText) findViewById(R.id.ed_name);        button_chaxun = (Button) findViewById(R.id.button_chaxun);         //绑定服务        Intent intent=new Intent("com.example.administrator.my_aidl_service.MyService");        MyServiceConnection myServiceConnection=new MyServiceConnection();        bindService(intent,myServiceConnection,BIND_AUTO_CREATE);        button_chaxun.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {                String name = ed_name.getText().toString().trim();                if(TextUtils.isEmpty(name)){                    Toast.makeText(MainActivity.this, "学号不能为空", Toast.LENGTH_SHORT).show();                }else{                    int id = Integer.parseInt(name);                    try {//调用接口对象的方法(就是调用真实对象的方法)                        String nameById = asInterface.queryNameById(id);                        text_name.setText(nameById);                    } catch (RemoteException e) {                        e.printStackTrace();                    }                }            }        });    }}
//在服务端注册Service

<service android:name=".MyService">    <intent-filter>        <action android:name="com.example.administrator.my_aidl_service.MyService"/>    </intent-filter></service>
//创建客户端。把服务端的AIDL文件复制到客户端,MakePoject一下。

//绑定远程服务

public class MainActivity extends AppCompatActivity {    private IMyAidlInterface asInterface;    private EditText ed_name;    private Button button_chaxun;    private TextView text_name;    private MyServiceConnection connection;    //绑定的服务是一个  远程的服务   aidl语言   传递过来的对象   :代理对象  代理对象不能直接使用    //需要使用Stub里面的一个方法  asInterface()把代理对象转化成真实对象  再使用    private class MyServiceConnection implements ServiceConnection{        @Override        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {            //把代理对象转化成真实对象            Toast.makeText(MainActivity.this, "连接成功", Toast.LENGTH_SHORT).show();            asInterface = IMyAidlInterface.Stub.asInterface(iBinder);        }        @Override        public void onServiceDisconnected(ComponentName componentName) {            Toast.makeText(MainActivity.this, "连接失败", Toast.LENGTH_SHORT).show();        }    }    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        text_name = (TextView) findViewById(R.id.text_name);        ed_name = (EditText) findViewById(R.id.ed_name);        button_chaxun = (Button) findViewById(R.id.button_chaxun);        //绑定服务        //Android5.0中service的intent一定要显性声明,当这样绑定的时候不会报错。        Intent intent=new Intent("com.example.administrator.my_aidl_service.MyService");        connection = new MyServiceConnection();        bindService(intent,connection,BIND_AUTO_CREATE);       button_chaxun.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {                String name = ed_name.getText().toString().trim();                if(TextUtils.isEmpty(name)){                    Toast.makeText(MainActivity.this, "学号不可为空", Toast.LENGTH_SHORT).show();                }else{                    int id = Integer.parseInt(name);                    try {                        String byId = asInterface.queryNameById(id);                        text_name.setText(byId);                    } catch (RemoteException e) {                        e.printStackTrace();                    }                }            }        });    }    @Override    protected void onDestroy() {        super.onDestroy();        unbindService(connection);    }}

原创粉丝点击