进程间通信(一)

进程通信的方式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
  • service.png
// 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,并且目录页必须相同,最好的办法是直接从服务端将目录和文件拷贝过去;

service.png

  • 在客户端需要进行通信的地方通过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);

service.png

 

和远程服务创建连接,通过onServiceConnected(ComponentName name, IBinder service)的远程IBinder service 得到IMyAidlInterface 实例myAidlInterface,通过这个实例就可以调用remote service中的接口了,这样我们的简单的aidl通信就建立起来了。

aidl通信支持的数据类型有:

  1. 八种基本数据类型:byte、char、short、int、long、float、double、boolean
  2. String,CharSequence ,实现了Parcelable接口的数据类型
  3. List ,Map    l他们承载的数据必须是AIDL支持的类型,或者是其它声明的AIDL对象

 

下一篇我们会学习一下aidl中传递实现了Parcelable接口的自定义数据类型

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值