最近做项目遇到一个问题,要通过我们的主应用给第三方应用发消息。至此接触到了AIDL。经过一番研究,终于懂了该怎么用了。在这里记录下来,一边后续继续了解
其中许多知识点都是参考http://www.poemcode.net/2010/05/aidl-ipc/
AIDL——android接口定义语言。它是一种android内部进程通信接口的描述语言,通过它我们可以定义进程间的通信接口。
要使用AIDL实现不同应用之间的通信,则主要部分就是实现.aidl文件。
1、实现.aidl文件 IMessage
package com.wyy.aidl; interface IMessage{ String getMessage(); }
aidl文件里就是主要是写接口,就是要进行通信的方法。
aidl文件里的代码跟java代码很类似,但也有许多不同之处。aidl文件里定义的接口不要有修饰符(如public private等)。
AIDL 支持的数据类型划分为四类,第一类是 Java 编程语言中的基本类型,第二类包括 String、List、Map 和 CharSequence,第三类是其他 AIDL 生成的 interface,第四类是实现了 Parcelable protocol 的自定义类。
其中,除了第一类外,其他三类在使用时均需要特别小心。
使用第二类时,首先需要明白这些类不需要 import,是内嵌的。其次注意在使用 List 和 Map 此二者容器类时,需注意其元素必须得是 AIDL 支持的数据类型,List 可支持泛型,但是 Map 不支持,同时另外一端负责接收的具体的类里则必须是 ArrayList 和 HashMap。
使用第三、四类时,需要留意它们都是需要 import 的,但是前者传递时,传递的是 reference,而后者则是 value。
在创建 .aidl 文件的过程中,应该注意一旦 method 有参数,则需注意在前面加上 in, out 或 inout,它们被称为 directional tag,但是对于基本类型的参数,默认就是 in,并且不会是其他值。
2、实现interface
AIDL 为你生成一个 interface 文件,文件名称和 .aidl 文件相同。如果使用 Eclipse 插件,则 AIDL 会在构建过程中自动运行,如果不使用插件,则需要先使用 AIDL。
生成的 interface 会包含一个抽象内部类 Stub,它声明了在 .aidl 文件里的所有方法。Stub 也定义了一些帮助方法,比较常用的有 asInterface(),其接收一个 IBinder 作为参数,并且返回一个 interface 的实例用来调用IPC方法。
要实现aidl里定义的接口,就需要了解service,新建一个项目作为service端,在service里实现Imessage.stub
public class MyService extends Service { private IBinder mIbinder = new MyBinder(); @Override public IBinder onBind(Intent intent) { // TODO Auto-generated method stub return mIbinder; } public String getS(){ return "从服务端获得的消息内容"; } private class MyBinder extends IMessage.Stub{ @Override public String getMessage() throws RemoteException { // TODO Auto-generated method stub return getS(); } } }
这个环节是重中之重,需要特别小心的有两点,其一是抛出的所有异常均不会发给调用者;其二是IPC调用是同步的,这意味IPC服务一旦花费较长时间完成的话,就会引起ANR,应该将这样的操作放在单独的线程里。
3、向客户端公开 Interface
public class MainActivity extends Activity { private TextView tv1; private MyConnection con = new MyConnection(); MyBroadCastReceive myReceiver = new MyBroadCastReceive(); private IMessage message; Intent it; DemoBService service1 = new DemoBService(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv1 = (TextView) findViewById(R.id.tv1); Intent service = new Intent("com.wyy.aidl.myservice"); if(bindService(service, con, BIND_AUTO_CREATE)){ Log.i("Mainactivity", "绑定成功"); } } private class MyConnection implements ServiceConnection{ @Override public void onServiceConnected(ComponentName name, IBinder service) { // TODO Auto-generated method stub Log.i("MyConnection--onServiceConnected()", "message != null"); message = IMessage.Stub.asInterface(service);
//在这里对获取到的信息进行操作
Log.i("MyConnection--onServiceConnected()", message.);
} @Override public void onServiceDisconnected(ComponentName name) { // TODO Auto-generated method stub Log.i("MyConnection--onServiceDisconnected()", "message ========= null"); message = null; } } }