进程通信的方式4种:
1、Activity,实际上是Intent/bundle 传值 比如我们要调用系统的电话界面拨打电话,系统短信界面发送短信,还有我们调用系统图片查看器或是三方APP来显示图片等等;
2、BroadCast 我们可以通过广播的模式来进行进程间通信,我们通过广播来发送需要传播的数据,然后通过在进程中注册广播接收器来接收数据;
3、contentProvider contentProvider的 存在就是为了向其他应用共享数据,让其他应用可以对自己的数据进行增删改查,我们Android系统中本身就实现了很多的ContentProvider:比如我们的音视频,联系人。
4、Service 实际上是 实际上是借助AIDL,或者基于AIDL的masenger,我们知道一般的Service其实是运行在所属app同一个进程中,并且是UI线程中,如果我们在service中的操作很耗时,那也必须要单独开一个线程的,系统有为我们提供IntentService。
下面主要说一下AIDL:包括服务端和客户端
- 服务端创建aidl文件IMyAidlInterface.aidl
// Declare any non-default types here with import statements
interface IMyAidlInterface {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
double aDouble, String aString);
int getSum(int a, int b);
void doExtro();
}
编译器会自动为我们生成IMyAidlInterface.java,注意其中的abstract class Stub,继承了我们的aidl接口,后面我们会主要用他来进行通信
// Declare any non-default types here with import statements
public interface IMyAidlInterface extends android.os.IInterface
{
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements com.xx.serverapplication.aidl.IMyAidlInterface
{
private static final java.lang.String DESCRIPTOR = "com.xx.serverapplication.aidl.IMyAidlInterface";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an com.xx.serverapplication.aidl.IMyAidlInterface interface,
* generating a proxy if needed.
*/
public static com.xx.serverapplication.aidl.IMyAidlInterface asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.xx.serverapplication.aidl.IMyAidlInterface))) {
return ((com.xx.serverapplication.aidl.IMyAidlInterface)iin);
}
return new com.xx.serverapplication.aidl.IMyAidlInterface.Stub.Proxy(obj);
}
@Override public android.os.IBinder asBinder()
{
return this;
}
@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
{
java.lang.String descriptor = DESCRIPTOR;
switch (code)
{
case INTERFACE_TRANSACTION:
{
reply.writeString(descriptor);
return true;
}
case TRANSACTION_basicTypes:
{
data.enforceInterface(descriptor);
int _arg0;
_arg0 = data.readInt();
long _arg1;
_arg1 = data.readLong();
boolean _arg2;
_arg2 = (0!=data.readInt());
float _arg3;
_arg3 = data.readFloat();
double _arg4;
_arg4 = data.readDouble();
java.lang.String _arg5;
_arg5 = data.readString();
this.basicTypes(_arg0, _arg1, _arg2, _arg3, _arg4, _arg5);
reply.writeNoException();
return true;
}
case TRANSACTION_getSum:
{
data.enforceInterface(descriptor);
int _arg0;
_arg0 = data.readInt();
int _arg1;
_arg1 = data.readInt();
int _result = this.getSum(_arg0, _arg1);
reply.writeNoException();
reply.writeInt(_result);
return true;
}
case TRANSACTION_doExtro:
{
data.enforceInterface(descriptor);
this.doExtro();
reply.writeNoException();
return true;
}
default:
{
return super.onTransact(code, data, reply, flags);
}
}
}
private static class Proxy implements com.xx.serverapplication.aidl.IMyAidlInterface
{
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote)
{
mRemote = remote;
}
@Override public android.os.IBinder asBinder()
{
return mRemote;
}
public java.lang.String getInterfaceDescriptor()
{
return DESCRIPTOR;
}
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
@Override public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, java.lang.String aString) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(anInt);
_data.writeLong(aLong);
_data.writeInt(((aBoolean)?(1):(0)));
_data.writeFloat(aFloat);
_data.writeDouble(aDouble);
_data.writeString(aString);
mRemote.transact(Stub.TRANSACTION_basicTypes, _data, _reply, 0);
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}
@Override public int getSum(int a, int b) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
int _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(a);
_data.writeInt(b);
mRemote.transact(Stub.TRANSACTION_getSum, _data, _reply, 0);
_reply.readException();
_result = _reply.readInt();
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
@Override public void doExtro() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_doExtro, _data, _reply, 0);
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}
}
static final int TRANSACTION_basicTypes = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_getSum = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
static final int TRANSACTION_doExtro = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
}
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, java.lang.String aString) throws android.os.RemoteException;
public int getSum(int a, int b) throws android.os.RemoteException;
public void doExtro() throws android.os.RemoteException;
}
- 服务端创建service,并在service中实例化一个Stub(我们的aidl接口类IMyAidlInterface.Stub iBinder)对象,并对我们定义的需要服务器端来完成的功能接口进行具体实现,再通过public IBinder onBind(Intent intent)返回这个实例IBinder;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.widget.Toast;
import com.xcheng.serverapplication.aidl.IMyAidlInterface;
public class MyService extends Service {
public MyService() {
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
return iBinder;
}
IMyAidlInterface.Stub iBinder = new IMyAidlInterface.Stub() {
@Override
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
}
@Override
public int getSum(int a, int b) throws RemoteException {
return a + b;
}
@Override
public void doExtro() throws RemoteException {
Toast.makeText(getApplicationContext(), "this is server doExtro", Toast.LENGTH_SHORT).show();
}
};
}
在 manifest 文件中对服务进行声明
<service
android:name=".MyService"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.aidl.service.test"/>
</intent-filter>
</service>
启动服务
startService(new Intent(this, MyService.class));
到这里服务端就准备好了,我们接着实现客户端
- 客户端需要创建服务端相同的aidl,并且目录页必须相同,最好的办法是直接从服务端将目录和文件拷贝过去;
- 在客户端需要进行通信的地方通过bindService绑定到服务端
ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
IMyAidlInterface myAidlInterface = IMyAidlInterface.Stub.asInterface(service);
try {
int sum = myAidlInterface.getSum(34, 54);
Toast.makeText(getApplicationContext(), "客户端调用服务器的getSum 计算,34 + 54 = " + sum, Toast.LENGTH_SHORT).show();
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
Intent service = new Intent();
service.setAction("com.aidl.service.test");
//从 Android 5.0开始 隐式Intent绑定服务的方式已不能使用,所以这里需要显式的设置Service所在服务端的包名否则会报如下图的运行时错误
service.setPackage("com.xx.serverapplication");
bindService(service,serviceConnection, BIND_AUTO_CREATE);
和远程服务创建连接,通过onServiceConnected(ComponentName name, IBinder service)的远程IBinder service 得到IMyAidlInterface 实例myAidlInterface,通过这个实例就可以调用remote service中的接口了,这样我们的简单的aidl通信就建立起来了。
aidl通信支持的数据类型有:
- 八种基本数据类型:byte、char、short、int、long、float、double、boolean
- String,CharSequence ,实现了Parcelable接口的数据类型
- List ,Map l他们承载的数据必须是AIDL支持的类型,或者是其它声明的AIDL对象
下一篇我们会学习一下aidl中传递实现了Parcelable接口的自定义数据类型