与绑定本地的Service不同的是,本地Service的onBinde()方法会直接把IBinder对象本身传给客户端的ServiceConnection。但是远程Service的onBind()方法只是将IBinder对象的代理传给客户端的ServiceConnection。
Android的AIDL定义了两个进程之间的通信接口,它的语法也很简单,和Java的接口定义相似,不过有几点区别:
1,AIDL定义接口代码文件必须以.aidl结尾;
2,AIDL接口中用到的数据类型,除了基本数据类型、String、List、Map、CharSequence之外,其他类型全部都需要导包,即便是他们在同一个包中也需要导包;
3,接口中只能定义方法;
在定义完AIDL接口后,AndroidSDK的工具aidl.exe会将该接口实现,你好会在gen/目录的相同包路径下看到接口的实现类,在这个实现类中有一个Stub的内部类,该内部类实现了IBinder、和你定义的AIDL接口,这个Stub就是远程Service的回调类,作为onBind()方法的返回值。在这个接口中有一个静态的asInterface(...)方法,这个方法会返回一个IBinder对象的代理。
AIDL接口:
package com.flyingduck.servicedemo3;
interface ICommunication{
String getServiceInfo();
}
Service端:
package com.flyingduck.servicedemo3;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
public class AIDLService extends Service {
private ICommunication.Stub comm = new ICommunication.Stub() {
@Override
public String getServiceInfo() throws RemoteException {
return "I'm from AIDLService";
}
};
@Override
public IBinder onBind(Intent arg0) {
return comm;
}
}
Manifest.xml
<service
android:name="com.flyingduck.servicedemo3.AIDLService"
android:process=":romote" >
</service>
Client端:
既然AIDL定义了两个进程间的通信接口,所以我们必须保证在客户端和服务端都会同时拥有这个接口。
package com.flyingduck.servicedemo3;
import android.app.Activity;
import android.app.Service;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class ClientActivity extends Activity {
private Button bindBtn;
private Button unbindBtn;
private TextView showTxt;
private ServiceConnection conn;
private ICommunication communication;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_client);
bindBtn = (Button) findViewById(R.id.bind_service);
unbindBtn = (Button) findViewById(R.id.un_bind_service);
showTxt = (TextView) findViewById(R.id.show);
conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
communication = ICommunication.Stub.asInterface(service);
try {
showTxt.setText(communication.getServiceInfo());
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
bindBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
bindService(new Intent(getApplicationContext(), AIDLService.class), conn, Service.BIND_AUTO_CREATE );
}
});
unbindBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
unbindService(conn);
}
});
}
}
这个例子简单的演示了AIDL的使用方法。实际上,服务需要接受不同应用的并发请求时才使用AIDL,如果我们只是想进行IPC(就是跨进程通信),并不需要处理多线程时,只需要使用 Messenger就可以了。
例子运行效果:
供参考文章:http://blog.csdn.net/saintswordsman/article/details/5130947
这里我们只是简单的传递了一个字符串,在进行跨进程通讯时,我们往往要传递一些较复杂的自定义类型,这时我们需要使用Android的序列化机制。