Fifteen, Android in AIDL IPC Supplemental --- use connection pooling Binder

Disclaimer: This article is a blogger original article, shall not be reproduced without the bloggers allowed. https://blog.csdn.net/yz_cfm/article/details/90612508

    In the Android multi-process communication, we use the most is AIDL. We have said a specific use AIDL, the client side of the connection service Service, and then combined by Binder returned from the server AIDL type of interface to allow clients to invoke methods of server and communicate with, the use of it is very simple. Imagine if the server AIDL define multiple interfaces, a AIDL interface is bound to a Service, it would mean that at the end of the service to open multiple backstage Service, 10 Ge can accept, 100 it? 1000 do? So apparently this is not feasible.

    Our solution is to manage services end all AIDL interfaces by defining a IBinderPool such AIDL interface and then only need to create a server bundled with IBinderPool Service, clients can bind like this that is a Service AIDL can obtain the desired type of interface and then make the appropriate method call. The idea is simple, it is similar to buying a house and sell the same, such Kwai Fong Park District houses the equivalent of every household AIDL multiple interfaces, the chain of home real estate agent area next to the service side of the interface is equivalent IBinderPool service side, the people who sell real estate information linked to the chain of intermediaries, and we want to buy a house only to find the chain of family mediation can be. That is, the client gets to IBinderPool can call AIDL interfaces we want to call. The following look at the concrete realization:

ICalculate1.aidl:

// ICalculate1.aidl
package com.cfm.binderpooltest;

interface ICalculate1 {
    // 提供加减法的计算器 1
    int add(int a, int b);
    int subtraction(int a, int b);
}

ICalculate2.aidl:

// ICalculate2.aidl
package com.cfm.binderpooltest;

interface ICalculate2 {
    // 提供乘除法的计算器 2
    int multip(int a, int b);
    int division(int a, int b);
}

IBinderPool.aidl:

// IBinderPool.aidl
package com.cfm.binderpooltest;

interface IBinderPool {
    IBinder queryBinder(int binderCode);
}

Calculate1Impl.java:

package com.cfm.binderpooltest;

/**
* 第一个 AIDL 接口的具体实现类
*/
public class Calculate1Impl extends ICalculate1.Stub {
    private static final String TAG = "cfmtest";

    @Override
    public int add(int a, int b) throws RemoteException {
        Log.d(TAG, "服务端开始计算加法");
        return (a+b);
    }

    @Override
    public int subtraction(int a, int b) throws RemoteException {
        Log.d(TAG, "服务端开始计算减法");
        return (a-b);
    }
}

Calculate2Impl.java:

package com.cfm.binderpooltest;

/**
*  第二个 AIDL 接口的具体实现类
*/
public class Calculate2Impl extends ICalculate2.Stub {
    private static final String TAG = "cfmtest";

    @Override
    public int multip(int a, int b) throws RemoteException {
        Log.d(TAG, "服务端开始计算乘法");
        return (a*b);
    }

    @Override
    public int division(int a, int b) throws RemoteException {
        Log.d(TAG, "服务端开始计算除法");
        return (a/b);
    }
}

BinderPoolService.java :( server)

package com.cfm.binderpooltest;

public class BinderPoolService extends Service {
    private static final String TAG = "cfmtest";
    private static final int BINDER_CALCULATE_1 = 1;
    private static final int BINDER_CALCULATE_2 = 2;
    private IBinder mBinderPool;

    public BinderPoolService() {

    }

    @Override
    public void onCreate() {
        Log.d(TAG, "客户端绑定服务成功!");
        super.onCreate();
        mBinderPool = new BinderPoolImpl();
    }

    /**
     *  客户端所获取到的 IBinder 接口,然后通过传入请求操作的 AIDL 接口对应的
     *  标示符,获取到相应的 AIDL 接口类型实例。
     */
    private class BinderPoolImpl extends IBinderPool.Stub {

        @Override
        public IBinder queryBinder(int binderCode) throws RemoteException {
            IBinder binder = null;
            switch (binderCode) {
                case BINDER_CALCULATE_1:
                    binder = new Calculate1Impl();
                    break;
                case BINDER_CALCULATE_2:
                    binder = new Calculate2Impl();
                    break;
                default:
                    break;
            }
            return binder;
        }
    }

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

ClientActivity.java :( clients)

package com.cfm.binderpooltest;

public class ClientActivity extends AppCompatActivity {
    private static final String TAG = "cfmtest";
    private static final int BINDER_CALCULATE_1 = 1;
    private static final int BINDER_CALCULATE_2 = 2;

    private ServiceConnection conn = new ServiceConnection() {
        
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            // 客户端连接服务端后返回的 Binder 类型是 IBinderPool
            IBinderPool binderPool = IBinderPool.Stub.asInterface(service);
            // 然后我们再调用 IBinderPool 中的 queryBinder 方法获取我们想要使用的 AIDL 接口
            try {
                ICalculate1 iCalculate1 = ICalculate1.Stub.asInterface(binderPool.queryBinder(BINDER_CALCULATE_1));
                ICalculate2 iCalculate2 = ICalculate2.Stub.asInterface(binderPool.queryBinder(BINDER_CALCULATE_2));
                Log.d(TAG, "客户端计算 6 加 2 为: " + iCalculate1.add(6, 2) );
                Log.d(TAG, "客户端计算 6 减 2 为: " + iCalculate1.subtraction(6, 2) );
                Log.d(TAG, "客户端计算 6 乘 2 为: " + iCalculate2.multip(6, 2) );
                Log.d(TAG, "客户端计算 6 除 2 为: " + iCalculate2.division(6, 2) );
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };

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

        // 绑定服务端
        Intent intent = new Intent(this, BinderPoolService.class);
        bindService(intent, conn, Context.BIND_AUTO_CREATE);
    }
}

AndroidManifest.xml:

...
        <service
            android:name=".BinderPoolService"
            android:enabled="true"
            android:exported="true"
            android:process=".remote">
        </service>

        <activity android:name=".ClientActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>

                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
...

Print Log Information:

Server:

2019-05-27 21:33:06.790 15680-15680/.remote D/cfmtest: 客户端绑定服务成功!
2019-05-27 21:33:06.853 15680-15695/.remote D/cfmtest: 服务端开始计算加法
2019-05-27 21:33:06.854 15680-15695/.remote D/cfmtest: 服务端开始计算减法
2019-05-27 21:33:06.856 15680-15695/.remote D/cfmtest: 服务端开始计算乘法
2019-05-27 21:33:06.857 15680-15695/.remote D/cfmtest: 服务端开始计算除法

Client:

2019-05-27 21:33:06.854 15661-15661/com.cfm.binderpooltest D/cfmtest: 客户端计算 6 加 2 为: 8
2019-05-27 21:33:06.855 15661-15661/com.cfm.binderpooltest D/cfmtest: 客户端计算 6 减 2 为: 4
2019-05-27 21:33:06.857 15661-15661/com.cfm.binderpooltest D/cfmtest: 客户端计算 6 乘 2 为: 12
2019-05-27 21:33:06.858 15661-15661/com.cfm.binderpooltest D/cfmtest: 客户端计算 6 除 2 为: 3

 

Guess you like

Origin blog.csdn.net/yz_cfm/article/details/90612508