一.概述
Android的Binder机制可以进行进程间通信,但是Servicemanager这个类不公开,也就是我在自己的应用程序中无法使用Servicemanager的addService将我们自己定义的service注册到binder中去,也无法通过getService获取到对应的Service,那么在我们的应用程序要如何来进行进程间通信呢?利用aidl文件和Service就可以进行通信了.
二.编写AIDL文件
在android studio按如上方法就可以创建aidl文件,在aidl文件中定义相关的功能,比如我在这里就定义了一个getString 方法:
将编写好的aidl文件编译就会生成同名的.java文件.为什么生成的aidl文件可以进行进程间通信呢,因为它会自动帮我们生成对应的Binder子类stub和对应的proxy类,至于这2个类是做什么的,这就涉及到了binder的知识,binder知识不是一下可以说清楚的,只能靠自己去研究了.
三.编写Service
public class WatchDogService extends Service {
public IBinder onBind(Intent intent) {
return new MyBind();
}
@Override
public void onDestroy() {
super.onDestroy();
}
@Override
public void onCreate() {
super.onCreate();
}
//这个类就是继承自aidl编译后生成的对应的.java件中的Stub类,它是Binder的子类
class MyBind extends test.Stub{
@Override
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
}
/**重写 getString 方法
@Override
public String getString(String str) throws RemoteException {
return "远程服务返回的数据:"+str;
}
}
}
四.将servie注册到AndroidManifest.xml中
<service android:name="com.betterda.test3.actiivty.WatchDogService">
<intent-filter>
<action android:name="com.lypeer.aidl"/>
<category android:name="android.intent.category.DEFAULT"/>
intent-filter>
service>
五.在另外一个应用程序中绑定servie
上面的service就定义在com.betterda.test3这个包名的应用程序中,接下来我在com.betterda.test2这个包名的应用程序中通过bindService来启动WatchDogService,然后调用test接口中定义的getString方法可以获取到WatchDogService返回的信息了,下面的代码就是bindservice
Intent intent = new Intent();
intent.setAction("com.lypeer.aidl");
intent.setPackage("com.betterda.test3");
if (!isBind) {
//因为是在另外一个程序的servie,所以只能通过action和package来绑定servie
bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
}
private ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
isBind = true;
//绑定成功以后,会返回在Service的onbind方法中返回的binder对象,我们在WatchDogService的onbind方法中返回就是new MyBind(),它是test.Stub类
//所以我们在这里可以得到Stub的Proxy对象
mTest = test.Stub.asInterface(service);
try {
//通过proxy的代理对象就可以调用getstring方法
String string = mTest.getString("你好");
Toast.makeText(MainActivity.this, string,0).show();
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
isBind = false;
Log.e(getLocalClassName(), "service disconnected");
}
};
在上面的代码中我们将绑定servive返回binder转换来test.Stub的Proxy对象,然后才能调用在test接口中定义的方法,所以在这个com.betterda.test2应用程序也要定义一个同样功能的aidl文件,这个只要将com.betterda.test3中定义的aidl文件拷贝过来,然后重新编译就会自定生成了,运行com.betterda.test2就可以看到getString返回:远程服务返回的数据:你好
六.总结
想要在进程间通信使用都是Binder机制,aidl和bindService就为了方便开发者在自己的应用程序中使用Binder机制来通信,bindService就是代替了ServiceManager的addService来向Binder驱动注册服务.