AIDL:Android Interface Definition Language,它是一种android内部进程通信接口的描述语言,通过它我们可以定义进程间的通信接口。
ICP:Interprocess Communication ,内部进程通信。
使用:
1、先创建一个aidl文件,aidl文件的定义和java代码类似,但是!它可以引用其它aidl文件中定义的接口和类,但是不能引用自定义的java类文件中定义的接口和类,要引用自定义的接口或类,需要为此类也定义一个对应的aidl文件,并且此类要实现Parcelable接口,同时aidl文件和类文件必须要在相同包下进行声明;Android包含了aidl编译器,当定义好一个aidl文件的时候,会自动编译生成一个java文件,此文件保存在gen目录之下。
在这个项目中,定义了两个aidl文件,其中Person实现了接口Parcelable,下面是这两个aidl文件的定义:
Person.aidl
{
parcelable Person;
}
IAIDLServerService.aidl
{ package com.webview; import com.webview.Person;// 引用上面的Person.aidl interface IAIDLServerService{ String sayHello(); Person getPerson(); } }
2、编写一个Service实现定义aidl接口中的内部抽象类Stub,Stub继承自Binder,并继承我们在aidl文件中定义的接口,我们需要实现这些方法。Stub中文意思存根,Stub对象是在服务端进程中被调用,即服务端进程。
在客户端调用服务端定义的aidl接口对象,实现Service.onBind(Intent)方法,该方法会返回一个IBinder对象到客户端,绑定服务时需要一个ServiceConnection对象,此对象其实就是用来在客户端绑定Service时接收Service返回的IBinder对象。
||public static abstract class Stub extends android.os.Binder implements com.webview.IAIDLServerService
public class AIDLServerService extends Service{ @Override public IBinder onBind(Intent intent) { return binder; } private IAIDLServerService.Stub binder = new Stub() { @Override public String sayHello() throws RemoteException { return "Hello AIDL"; } @Override public Person getPerson() throws RemoteException { Person person = new Person(); person.setName("Livingstone"); person.setAge(22); return person; } }; }
3、在服务端注册Service,将如下代码添加进Application节点之下!
<service android:name="com.webview.AIDLServerService"
android:process=":remote">
<intent-filter>
<action android:name="com.webview.IAIDLServerService"></action>
</intent-filter>
</service>
至此,服务端进程定义已经完成!
4、编写客户端,注意需要在客户端存一个服务端实现了的aidl接口描述文件,客户端只是使用该aidl接口,获取服务端的aidl对象(IAIDLServerService.Stub.asInterface(service))之后就可以调用接口的相关方法,而对象的方法的调用不是在客户端执行,而是在服务端执行。
public class MainActivity extends Activity { private Button btn; private IAIDLServerService aidlService = null; private ServiceConnection conn = new ServiceConnection() { @Override public void onServiceDisconnected(ComponentName name) { aidlService = null; } @Override public void onServiceConnected(ComponentName name, IBinder service) { aidlService = IAIDLServerService.Stub.asInterface(service); try { aidlService.doFunction();// 执行接口定义的相关方法 } catch (RemoteException e) { e.printStackTrace(); } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btn = (Button) findViewById(R.id.button); tv = (TextView) findViewById(R.id.textview); btn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Intent service = new Intent("com.webview.IAIDLServerService"); bindService(service, conn, BIND_AUTO_CREATE);// 绑定服务 } }); } }
客户端目录结构:
Messenger:
它引用了一个Handler对象,以便others能够向它发送消息(使用mMessenger.send(Message msg)方法)。该类允许跨进程间基于Message的通信(即两个进程间可以通过Message进行通信),在服务端使用Handler创建一个Messenger,客户端持有这个Messenger就可以与服务端通信了。
1.Service实现Handler接口用于接客户端的请求
2.Handler是要用于创建一个Messenger对象,这个对象要引用此Handler
3.Messenger创建一个IBinder,并且在Service的onBind()方法中返回给客户端
4.客户端用服务端返回的IBider对象实例化一个Messenger,此Messenger用于发送Message到Service服务端
5.服务端接收每一个Message,并且在Handler中对消息进行处理-->handleMessage()
6.如果需要服务端进行用户请求响应,需要在发送消息到服务端的时候,让Message引用客户端的Messenger对象(Handler.replyTo=Messenger),然后再调用Messenger的send()方法。这样服务端接收到消息的同时也得到了客户端的Messenger对象,服务端就可以通过客户端的Messenger对象向客户端发送消息。
这种方法,没有用于供客户端调用的方法,而是客户端发送消息到服务端,服务端接到消息后对消息进行相应的处理!
public class MSGService extends Service { Messenger mMessenger = new Messenger(new myHandler()); class myHandler extends Handler { @Override public void handleMessage(Message msg) { switch (msg.what) { case 1: Toast.makeText(getApplicationContext(), "Hello", 1).show(); break; } } } @Override public IBinder onBind(Intent intent) { return mMessenger.getBinder(); } } public class MainActivity extends Activity { Messenger mService = null; boolean bound = false; @Override protected void onStart() { super.onStart(); Intent intent = new Intent(); intent.setClassName("com.broadlistener", "com.broadlistener.MSGService"); bindService(intent, conn, Context.BIND_AUTO_CREATE); } private ServiceConnection conn = new ServiceConnection() { @Override public void onServiceDisconnected(ComponentName name) { } @Override public void onServiceConnected(ComponentName name, IBinder service) { mService = new Messenger(service); bound = true; } }; public void click(View v) { if (bound) { Message msg = Message.obtain(null, 1, 0, 0); try { msg.replyTo = mService;// [6] mService.send(msg); } catch (RemoteException e) { e.printStackTrace(); } } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } }