AIDL实现两个进程通信

前言
aidl是用于Android 进程间通信的一种方式,通过使用aidl,A进程可以调用B进程的Service中的方法,从而实现数据传递和通信。

下面用一个简单实例一步步实现aidl通信,此次实例需要一个Server项目和一个Client项目,我们想实现的是,Client进程可以从Server进程中获取数据。

Server端实现

新建Server空项目,然后按如下方式新建aidl文件:

输入aidl文件名之后,Android studio会自动把aidl文件放到一个和Android 项目的java文件相同包名的文件夹下,如图所示:

生成的aidl文件我们命名为IMyAidlInterface.aidl,它的包名为example.hp.aidlserver,和java文件对应的包名是一模一样的。

将IMyAidlInterface.aidl的文件内容修改如下:

package example.hp.aidlserver;

interface IMyAidlInterface {
    int getValue();  //自定义的抽象方法,供cilent进程调用
}

此时把Server项目运行一下,就会发现在Build目录下生成了IMyAidlInterface.java文件:
这里写图片描述

打开这个IMyAidlInterface.java文件,可以看到这个Java类内容如下,
下面的代码都是项目自动生成的:

package example.hp.aidlserver;

public interface IMyAidlInterface extends android.os.IInterface {
    /**
     * Local-side IPC implementation stub class.
     */
    public static abstract class Stub extends android.os.Binder implements example.hp.aidlserver.IMyAidlInterface {
        private static final java.lang.String DESCRIPTOR = "example.hp.aidlserver.IMyAidlInterface";

        /**
         * Construct the stub at attach it to the interface.
         */
        public Stub() {
            this.attachInterface(this, DESCRIPTOR);
        }

        /**
         * Cast an IBinder object into an example.hp.aidlserver.IMyAidlInterface interface,
         * generating a proxy if needed.
         */
        public static example.hp.aidlserver.IMyAidlInterface asInterface(android.os.IBinder obj) {
            if ((obj == null)) {
                return null;
            }
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin != null) && (iin instanceof example.hp.aidlserver.IMyAidlInterface))) {
                return ((example.hp.aidlserver.IMyAidlInterface) iin);
            }
            return new example.hp.aidlserver.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 {
            switch (code) {
                case INTERFACE_TRANSACTION: {
                    reply.writeString(DESCRIPTOR);
                    return true;
                }
                case TRANSACTION_getValue: {
                    data.enforceInterface(DESCRIPTOR);
                    int _result = this.getValue();
                    reply.writeNoException();
                    reply.writeInt(_result);
                    return true;
                }
            }
            return super.onTransact(code, data, reply, flags);
        }

        private static class Proxy implements example.hp.aidlserver.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;
            }

            @Override
            public int getValue() 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);
                    mRemote.transact(Stub.TRANSACTION_getValue, _data, _reply, 0);
                    _reply.readException();
                    _result = _reply.readInt();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }
        }

        static final int TRANSACTION_getValue = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
    }

    public int getValue() throws android.os.RemoteException;
}

其中有个Stub内部类非常重要,它就是我们实现aidl通信的关键,它继承了Binder类,并实现了IMyAidlInterface接口。

接下来,我们要在Server项目里定义一个Service,供Client进程通过bindService的方式进行调用。这个Service建立在java目录下,命名为MyService.class:

package example.hp.aidlserver;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;

public class MyService extends Service {

    IMyAidlInterface.Stub stub = new IMyAidlInterface.Stub() {
        @Override
        public int getValue() throws RemoteException {
            return 99;
        }
    };

    public MyService() {
    }

    @Override
    public void onCreate() {
        super.onCreate();
    }

    @Override
    public IBinder onBind(Intent intent) {
        return stub;
    }

}

可以看到,我们在MyService的onBind方法里返回了一个IMyAidlInterface.Stub的对象,这个对象实现了aidl接口定义的getValue()方法,返回值为99。

Client端实现
新建Client项目,然后把Server项目的aidl整个文件夹拷贝过来,放到Client项目里。注意是完全拷贝,不用做任何修改,拷贝过来后的Client项目结构如下:

然后我们就可以在Client端的activity里,通过bindServer的方式拿到Server端的Binder实例,从而可以调用getValue()方法,具体怎么做呢?如下是Client端的activity代码,我们让页面打开的时候从Server端获取数据:

package example.hp.aidlclient;

import android.app.Activity;
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.util.Log;

import example.hp.aidlserver.IMyAidlInterface;

public class ClientMainActivity extends Activity {
    private boolean mBound = false;

    private static final String TAG = "MyService";
    ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            Log.d(TAG, "onServiceConnected");
            mBound = true;
            IMyAidlInterface iface = IMyAidlInterface.Stub.asInterface(iBinder);
            try {
                int value = iface.getValue();
                Log.d(TAG, "get value: " + value);
            } catch (RemoteException e) {
                e.printStackTrace();
            }

        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {

        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_client_main);

        Intent intent = new Intent();
        ComponentName componentName = new ComponentName("example.hp.aidlserver", "example.hp.aidlserver.MyService");
        intent.setComponent(componentName);
        bindService(intent, connection, BIND_AUTO_CREATE);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mBound) {
            unbindService(connection);
        }
    }
}

先运行Server,再运行Client,运行后打印结果为:

02-28 22:18:35.566 29647-29647/example.hp.aidlclient D/MyService: onServiceConnected
02-28 22:18:35.566 29647-29647/example.hp.aidlclient D/MyService: get value: 99

可见Client进程已经成功地获取到了Server进程的数据。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android AIDLAndroid Interface Definition Language)是一种Android中用于实现进程通信的机制。它允许一个应用程序的进程与另一个应用程序的进程进行交互。 在AIDL中,双向通信可以通过以下步骤实现: 1. 创建AIDL接口:首先,在服务提供方的应用程序中创建一个AIDL接口类,该接口定义了需要在两个应用程序之间进行通信的方法。 2. 实现AIDL接口:在服务提供方的应用程序中实现AIDL接口。这些方法将用于处理由客户端发起的请求。 3. 绑定Service:在客户端应用程序中,通过绑定Service与提供方建立连接。这可以通过Intent和bindService()方法完成。 4. 获取Service接口:一旦客户端与服务提供方建立了连接,客户端将获得Service的接口。这个接口将通过onServiceConnected()方法返回给客户端。 5. 调用方法:客户端可以使用接口对象来调用服务提供方的方法,从而向服务提供方发送请求。 6. 返回结果:服务提供方在接收到请求后,根据请求的类型进行相应的处理,并将处理结果返回给客户端。 通过以上步骤,双向通信将会在两个应用程序之间建立起来。服务提供方可以处理客户端的请求,并将结果返回给客户端。而客户端可以调用服务提供方的方法,并获取所需的数据。 需要注意的是,为了保证AIDL双向通信的正常运行,需要在AndroidManifest.xml文件中声明相应的权限和服务。 总结来说,使用Android AIDL可以实现双向通信。服务提供方与客户端通过AIDL接口进行交互,客户端发送请求给服务提供方,并获取处理结果。这种机制可以方便地实现不同应用程序之间的数据交换和通信。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值