提起进程间的通信我们就会想到Aidl,今天就个人理解的Aidl进行阐述,如有不当之处还望大家多多指教。好了,不说废话了,下面我们就进入今天的正题——Aidl,进程间的通信大使。

AIDL是一个缩写,全称是Android Interface Definition Language,也就是Android接口定义语言。是的,首先我们知道的第一点就是:AIDL是一种语言。既然是一种语言,那么相应的就很自然的衍生出了一些问题:

为什么要设计出这么一门语言?

它有哪些语法?

我们应该如何使用它?

下面我们就这些问题进行分开描述:

为什么要设计出这么一门语言?

设计这门语言的目的是为了实现进程间通信。
每一个进程都有自己的Dalvik VM实例,都有自己的一块独立的内存,都在自己的内存上存储自己的数据,执行着自己的操作,都在自己的那片狭小的空间里过完自己的一生。每个进程之间都你不知我,我不知你,就像是隔江相望的两座小岛一样,都在同一个世界里,但又各自有着自己的世界。而AIDL,就是两座小岛之间沟通的桥梁。相对于它们而言,我们就好像造物主一样,我们可以通过AIDL来制定一些规则,规定它们能进行哪些交流——比如,它们可以在我们制定的规则下传输一些特定规格的数据。
总之,通过这门语言,我们可以愉快的在一个进程访问另一个进程的数据,甚至调用它的一些方法

它有哪些语法

其实AIDL这门语言非常的简单,基本上它的语法和 Java 是一样的,只是在一些细微处有些许差别——毕竟它只是被创造出来简化Android程序员工作的,太复杂不好——所以在这里我就着重的说一下它和 Java 不一样的地方。主要有下面这些点:
文件类型:用AIDL书写的文件的后缀是 .aidl,而不是 .java。
数据类型: Java基本类型,String,List,Map,CharSequence

我们如何使用它?

IBinder是远程对象的基本接口,是为了高性能而设计的轻量级远程调用机制的核心部分。但他 不仅用于远程调用,也用于进程内调用。该接口定义了与远程对象间交互的协议。但不要直接实现 这个接口,而是继承(extends)Binder。

IBinder是Android给我们提供的一个进程间通信的一个接口,而我们一般是不直接实现这个接口的, 而是通过继承Binder类来实现进程间通信!是Android中实现IPC(进程间通信)的一种方式!

Binder机制给我们带来的最直接的好处就是: 我们无需关心底层如何实现,只需按照AIDL的规则,自定义一个接口文件, 然后调用调用接口中的方法,就可以完成两个进程间的通信了!


到这里相信大家已经对Aidl有了一定的了解,那么此时,问题又来了。什么是IPC啊?它又是个什么鬼?别急别急,容我歇息一番后做出解答。

IPC这个名词,他的全名叫做:跨进程通信(interprocess communication), 因为在Android系统中,个个应用程序都运行在自己的进程中,进程之间一般是无法直接进行数据交换的, 而为了实现跨进程,Android给我们提供了上面说的Binder机制,而这个机制使用的接口语言就是: AIDL(Android Interface Definition Language)

这种接口语言并非真正的编程 语言,只是定义两个进程间的通信接口而已!而生成符合通信协议的Java代码则是由Android SDK的 platform-tools目录下的aidl.exe工具生成,生成对应的接口文件在:gen目录下,一般是:Xxx.java的接口! 而在该接口中包含一个Stub的内部类,该类中实现了在该类中实现了IBinder接口与自定义的通信接口, 这个类将会作为远程Service的回调类——实现了IBinder接口,所以可作为Service的onBind( )方法的返回值!

在开始编写AIDL接口文件前,我们需要了解下编写AIDL的一些注意事项:
AIDL注意事项:
接口名称需要与aidl文件名相同
接口和方法前面不要加访问权限修饰符:public ,private,protected等,也不能用static final!
AIDL默认支持的类型包括Java基本类型,String,List,Map,CharSequence,除此之外的其他类型都 需要import声明,对于使用自定义类型作为参数或者返回值,自定义类型需要实现Parcelable接口


说了这么多,接下来当然就是贴代码了,但是,再贴代码之前,还是先给出步骤:

服务端步骤如下:

Step 1:创建AIDL文件:
Step 2:自定义我们的Service类,完成下述操作:
1)继承Service类,同时也自定义了一个类用来继承MyServiceAIDL.Stub类 就是实现了MyServiceAIDL接口和IBinder接口
2)实例化自定义的Stub类,并重写Service的onBind方法,返回一个binder对象!
Step 3:在AndroidManifest.xml文件中注册Service

客户端步骤如下:

直接把服务端的那个aidl文件复制过来(包名要一致)

1)创建 ServiceConnection接口 实例

2) 调用bindService绑定远程Service bindService(service,conn,BIND_AUTO_CREATE); 

3)和本地Service不同,绑定远程Service的ServiceConnection并不能直接获取Service的onBind( )方法 返回的IBinder对象,只能返回onBind( )方法所返回的代理对象,需要做如下处理: binder= MyServiceAIDL.Stub.asInterface(service); 再接着完成初始化,以及按钮事件等就可以了


下面给出代码:

首先是aidl文件:它的后缀名一定要是.aidl

package us.mifeng;interface Authority{String getName(int num);}
服务端service:

public class MyService extends Service{String name[]={"11","22","33","44","55"};@Overridepublic void onCreate() {super.onCreate();}@Overridepublic IBinder onBind(Intent intent) {return new MyBinder();}class MyBinder extends Stub{@Overridepublic String getName(int num) throws RemoteException {int i = num%5;return name[i];}}}
清单文件中的代码如下:

                                                                 
然后就是客户端的代码了。在这之前一定要先把服务端的aidl文件copy过来。一定一定。。。


public class MainActivity extends Activity {private Button mBtn;private EditText mEd;private TextView mTv;private Authority binder;private ServiceConnection conn=new ServiceConnection() {@Overridepublic void onServiceDisconnected(ComponentName name) {}@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {Log.e("", "===================");binder = Authority.Stub.asInterface(service);}};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mBtn=(Button) findViewById(R.id.mBtn);mEd=(EditText) findViewById(R.id.mEd);mTv=(TextView) findViewById(R.id.mTv);Intent intent =new Intent();intent.setAction("cn.bgs.aidldemo");bindService(intent, conn, Service.BIND_AUTO_CREATE);mBtn.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {               int result=Integer.valueOf(mEd.getText().toString());try {String data=binder.getName(result);Log.e("", "================="+data);mTv.setText(data);} catch (RemoteException e) {e.printStackTrace();}}});}}

忘记说一件事情,前几天在给学生讲这个代码的时候,遇到了一个小小的bug,那就是空指针异常,在我查阅资料后发现是因为 在android 5.0之后不能采用隐式跳转,需要在intent.setAction();方法之后,加一行代码。 即intent.setPackage("服务端MyService的包名");

然后,方便以后有遇到这个问题的新手查阅,特写此博客。(允许我小小的装一下逼(●'◡'●))。


更多相关文章

  1. 分支和循环(二)(零基础学习C语言)
  2. 一款霸榜 GitHub 的开源 Linux 资源监视器!
  3. Android内存监控与分析(一):内存泄漏(Memory Leak)与内存溢出(OOM)的表
  4. android 用户界面事件
  5. Android中Adapter和Bridge模式理解和应用
  6. Android(安卓)技术: 追踪vm 如何调用基础类
  7. Android集成测试
  8. [置顶] android 跨进程通信
  9. Android中Intent传递自定义对象类型的数据

随机推荐

  1. 一起学android之如何以最简单方式开启闪
  2. ffmpeg 编译至android
  3. Android回调接口简单理解
  4. android中的加密传输
  5. android的全局定时器AlarmManager详解
  6. android studio导工程出现Error:Executio
  7. android多线程断点续传
  8. Android(安卓)Dialog弹出时背景全透明
  9. Android五大存储之SQLite
  10. 使用android framework源码编译自己apk问