###简介
AIDL适用于跨进程的通信,以下实现了跨APP通信的功能,包括服务端和客户端。
其中服务端提供AIDL服务访问的接口,客户端根据这个接口去访问服务,获取信息。
源代码的地址:http://download.csdn.net/detail/hbdatouerzi/9911205
经过测试,程序在谷歌平板上能够正确的运行,但是在魅族手机上无法连接到服务。
###实现
####1.服务端
1)新建项目AIDL_Server,并在main文件夹下创建aidl文件,新建ICat.aidl文件
其中ICat.aidl代码如下
interface ICat {
void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
double aDouble, String aString);
String getColor();
double getWeight();
}
2)build project,项目会自动根据AIDL文件生成对应的Java文件。
其中,生成ICat.java 类当中会包含一个Stub的内部类,它是Binder和ICat的子类。
3)创建CatServer
当有客户端来连接的时候,会调用onBind()函数,这时候返回一个mBinder对象,它是Stub的实例,包含了服务端返回给客户端的消息。
public class CatServer extends Service{
private String tag = "CatServer";
@Override
public void onCreate() {
super.onCreate();
Log.i(tag,"开启CatServer服务");
}
@Override
public void onDestroy() {
super.onDestroy();
Log.i(tag,"销毁CatServer服务");
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
private Binder mBinder = new ICat.Stub() {
@Override
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
}
@Override
public String getColor() throws RemoteException {
return "红色";
}
@Override
public double getWeight() throws RemoteException {
return 5;
}
};
}
4)在AndroidManifest.xml文件当中注册Service
其中设置process属性,能够允许远程访问服务;action属性,指定访问的服务。
这样,服务端的工作就完成了,不需要有界面,也不需要手动去开启关闭服务。
####2.客户端
1)新建项目AIDL_Client
并将服务端的AIDL文件夹复制到客户端对应的位置,也可以自己新建,但是要保证包名和aidl文件一致,否则访问会出现异常。
服务端的aidl路径:
客户端的aidl路径:
2)build project
同样,这时候build project会自动生成ICat.java文件。
3)服务连接监听
当服务连接成功之后,服务端返回的IBinder对象,我们可以将其转化为ICat对象,这样就可以获取到我们想要的信息了。
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
Log.i(tag,"连接成功!");
ICat cat = ICat.Stub.asInterface(iBinder);
try{
String color = cat.getColor();
double weight = cat.getWeight();
Log.i(tag,color+","+weight);
}catch(Exception e){
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
Log.i(tag,"断开连接");
}
};
4)访问服务
Android5.0之后,不能再使用隐式的intent,可以使用createExplicitFromImplicitIntent函数,将其转化为显式的intent。
@Override
public void onClick(View view) {
if(get_server_btn == view){
Log.i(tag,"获取服务");
Intent intent = new Intent("com.example.huangbei.aidl_server.CatServer");
final Intent eintent = new Intent(createExplicitFromImplicitIntent(this,intent));
bindService(eintent,mConnection, Service.BIND_AUTO_CREATE);
}
}
//将隐式intent转化为显式的intent
public static Intent createExplicitFromImplicitIntent(Context context, Intent implicitIntent) {
// Retrieve all services that can match the given intent
PackageManager pm = context.getPackageManager();
List resolveInfo = pm.queryIntentServices(implicitIntent, 0);
// Make sure only one match was found
if (resolveInfo == null || resolveInfo.size() != 1) {
return null;
}
// Get component info and create ComponentName
ResolveInfo serviceInfo = resolveInfo.get(0);
String packageName = serviceInfo.serviceInfo.packageName;
String className = serviceInfo.serviceInfo.name;
ComponentName component = new ComponentName(packageName, className);
// Create a new intent. Use the old one for extras and such reuse
Intent explicitIntent = new Intent(implicitIntent);
// Set the component to be explicit
explicitIntent.setComponent(component);
return explicitIntent;
}
###总结
学习AIDL让我想到,如果有流氓软件A和B,A开启一个AIDL服务。然后当B启动的时候,去访问这个服务,当A收到访问服务的请求之后,打开自己的后台服务,并返回。这样用户只想要开启一个APP,结果相当于开启了两个。