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.aidl package com.example.administrator.my_aidl_service; // Declare any non-default types here with import statements interface 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); } }