什么是AIDL?
AIDL:Android Interface Definition Language,即Android接口定义语言。
Android系统中的进程之间不能共享内存,因此,需要提供一些机制在不同进程之间进行数据通信。
为了使其他的应用程序也可以访问本应用程序提供的服务,Android系统采用了远程过程调用(Remote Procedure Call,RPC)方式来实现。与很多其他的基于RPC的解决方案一样,Android使用一种接口定义语言(Interface Definition Language,IDL)来公开服务的接口。我们知道4个Android应用程序组件中的3个(Activity、BroadcastReceiver和ContentProvider)都可以进行跨进程访问,另外一个Android应用程序组件Service同样可以。因此,可以将这种可以跨进程访问的服务称为AIDL(Android Interface Definition Language)服务
接着建立AIDL服务端步骤
1,在Eclipse Android工程的Java包目录中建立一个扩展名为aidl的文件。该文件的语法类似于Java代码,但会稍有不同
在这个文件中只定义了一个接口
package huahua.myaidlserver;
interface Ihuahua {
String greet(String someone);
}
上图中R.java上的那个Ihuahua.java就是系统自动生成的,这个文件不用管它,到时候在客户端需要用到
3,建立一个服务类AIDLServer,并实现由aidl文件生成的Java接口
package huahua.myaidlserver;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
public class AIDLService extends Service {
private static final String TAG = "huahua.AIDLService";
Ihuahua.Stub stub = new Ihuahua.Stub() {
@Override
public String greet(String someone) throws RemoteException {
Log.i(TAG, "greet() called");
return "Hello " + someone+ "!";
}
};
@Override
public void onDestroy() {
Log.i(TAG, "onDestroy() called");
super.onDestroy();
}
@Override
public boolean onUnbind(Intent intent) {
Log.i(TAG, "onUnbind() called");
return true;
}
@Override
public IBinder onBind(Intent intent) {
Log.i(TAG, "onBind() called");
return stub;
}
}
Stub是存根的意思,在服务端创建Ihuahua.Stub对象,并且真正实现了Ihuahua.aidl接口中的方法.
android:label="@string/app_name" >
好了,这个服务端的程序就写完了,就只提供了一个接口而已
需要注意的是,这个服务端程序是一个后台程序,没有界面显示!
下面是客户端的实现
新建一个Android应用程序MyAIDLClient,然后把MyAIDLServer程序中gen/huahua目录中的myaidlserver文件夹拷贝到新程序中的src/huahua目录下(huahua这个包名可以任意修改)
拷贝过去以后,只用保留Ihuahua.java系统自动生成的这个java文件,其他的都可以删掉
接着就可以编写主Activity代码了
package huahua.myaidlclient;
import huahua.myaidlserver.Ihuahua;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends Activity {
private Button btn1;
private Button btn2;
private Button btn3;
private Ihuahua ihuahuadashen;
private ServiceConnection SC = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
Log.i("ServiceConnection", "onServiceDisconnected() called");
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.i("ServiceConnection", "onServiceConnected() called");
ihuahuadashen = Ihuahua.Stub.asInterface(service);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn1 = (Button)findViewById(R.id.btn1);
btn1.setOnClickListener(new BtnClick());
btn2 = (Button)findViewById(R.id.btn2);
btn2.setOnClickListener(new BtnClick());
btn3 = (Button)findViewById(R.id.btn3);
btn3.setOnClickListener(new BtnClick());
btn1.setEnabled(true);
btn2.setEnabled(false);
btn3.setEnabled(false);
}
private class BtnClick implements View.OnClickListener{
@Override
public void onClick(View v) {
if(v.getId() == R.id.btn1)
{
Intent intent = new Intent("huahuadashen.AIDLService");
bindService(intent, SC, Context.BIND_AUTO_CREATE);
btn1.setEnabled(false);
btn2.setEnabled(true);
btn3.setEnabled(true);
}
else if(v.getId() == R.id.btn2)
{
unbindService(SC);
btn1.setEnabled(true);
btn2.setEnabled(false);
btn3.setEnabled(false);
}
else if(v.getId() == R.id.btn3)
{
try {
String str = ihuahuadashen.greet("everyone");
Toast.makeText(MainActivity.this, str, Toast.LENGTH_SHORT).show();
} catch (RemoteException e) {
Toast.makeText(MainActivity.this, "异常", Toast.LENGTH_SHORT).show();
e.printStackTrace();
}
}
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
就实现了3个功能
第1个按钮是绑定服务端,intent中的参数"huahuadashen.AIDLService"要和服务端AndroidManifest.xml中声明的行为
第2个按钮取消绑定
绑定成功后,第3个按钮就可以用Ihuahua的对象来调用相应的接口了
可以看到在客户端程序中并不需要用到扩展名为aidl的文件,而且对于接口中的具体功能实现也看不到,
这个服务端程序跟C++中的动态库程序是不是有点相似呢,都是提供封装的接口给其他程序调用
下面是源代码地址
AIDL源码下载