AIDL实现两个进程通信

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

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

Server端实现

新建Server空项目,然后按如下方式新建aidl文件:
AIDL实现两个进程通信_第1张图片

输入aidl文件名之后,Android studio会自动把aidl文件放到一个和Android 项目的java文件相同包名的文件夹下,如图所示:
AIDL实现两个进程通信_第2张图片
生成的aidl文件我们命名为IMyAidlInterface.aidl,它的包名为example.hp.aidlserver,和java文件对应的包名是一模一样的。

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

package example.hp.aidlserver;

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

此时把Server项目运行一下,就会发现在Build目录下生成了IMyAidlInterface.java文件:
AIDL实现两个进程通信_第3张图片

打开这个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项目结构如下:
AIDL实现两个进程通信_第4张图片

然后我们就可以在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进程的数据。

你可能感兴趣的:(Android)