Android16_Binder连接池

AIDL进行线程间通信,随着项目规模的扩大,如果有多个业务模块都需要使用AIDL进行进程间通信;

如果按照AIDL的实现方式,需要一个个来实现,创建多个Service。

但这样有个问题,Service不能无限制地增加,Service是系统组件之一,本身就是系统资源。

太多Service会使得我们地应用看起来很重量级。

我们需要减少Service的数量,将所有的AIDL放在同一个Service中去管理。

 

整个模式的工作机制是这样的:

每个业务模块创建自己的AIDL接口并实现此接口;

这个时候不同的业务模块之间是不能耦合的,所有实现的细节要单独开来;

然后向服务端提供自己的唯一标识和其对应的Binder对象;

对于服务端来说,只需要一个Service就可以了,服务端提供一个queryBinder接口

这个接口能够根据业务模块的特征,来返回相应的Binder对象给它们,不同的业务模块拿到所需的Binder对象后,就可以进行远程方法调用了。

Binder连接池的主要作用是将每个业务模块的Binder请求统一转发到远程Service中去执行;

从而避免了重复创建Service的过程;

 

 

 

 

 

====================================================

 这里创建了两个工程,一个是客户端,一个是服务端;

先看下服务端代码:

 

 

Manifest代码

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.learnbinderpool_service">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme" >
        <service
            android:name=".BinderPoolService"
            android:enabled="true"
            android:exported="true">
        </service>
    </application>
</manifest>

 

BinderPoolService代码:

package com.example.learnbinderpool_service;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;

public class BinderPoolService extends Service {
    private static final String TAG = "BinderPoolService";

    private Binder mBinderPool = new BinderPoolImpl();

    public BinderPoolService() {
    }

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

    @Override
    public IBinder onBind(Intent intent) {
        Log.d(TAG,"onBind");
        return mBinderPool;
    }

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

 

接着是三个AIDL接口的实现

ComputeImpl.java

package com.example.learnbinderpool_service;

import android.os.RemoteException;

public class ComputeImpl extends ICompute.Stub {
    @Override
    public int add(int a, int b) throws RemoteException{
        return a+b;
    }
}

 

SecurityCenterImpl.java

package com.example.learnbinderpool_service;

import android.os.RemoteException;

//实现AIDL接口
public class SecurityCenterImpl extends ISecurityCenter.Stub{
    private static final char SECRET_CODE = '^';

    @Override
    public String encrypt(String content) throws RemoteException {
        char[] chars = content.toCharArray();
        for(int i = 0; i<chars.length; i++){
            chars[i] ^= SECRET_CODE;
        }
        return new String(chars);
    }

    @Override
    public String decrypt(String password) throws RemoteException{
        return encrypt(password);
    }
}

 

BinderPoolImpl.java

package com.example.learnbinderpool_service;

import android.os.IBinder;
import android.os.RemoteException;


public class BinderPoolImpl extends IBinderPool.Stub {
    public static final int BINDER_NONE = -1;
    public static final int BINDER_COMPUTE = 0;
    public static final int BINDER_SECURITY_CENTER = 1;

    @Override
    public IBinder queryBinder(int binderCode) throws RemoteException{
        IBinder binder = null;
        switch (binderCode){
            case BINDER_SECURITY_CENTER:{
                binder = new SecurityCenterImpl();
                break;
            }
            case BINDER_COMPUTE:{
                binder = new ComputeImpl();
                break;
            }
            default:
                break;
        }
        return binder;
    }
}

 

AIDL接口声明:

// IBinderPool.aidl
package com.example.learnbinderpool_service;

// Declare any non-default types here with import statements

interface IBinderPool {
    IBinder queryBinder(int binderCode);
}
// ICompute.aidl
package com.example.learnbinderpool_service;

// Declare any non-default types here with import statements

interface ICompute {
    int add(int a, int b);
}
// ISecurityCenter.aidl
package com.example.learnbinderpool_service;

// Declare any non-default types here with import statements

interface ISecurityCenter {
    String encrypt(String content);
    String decrypt(String password);
}

 

================================================================

然后是客户端工程代码:

 

 

 

Manifest

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.learnbinderpool_client">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

</manifest>

 

BinderPool.java

 

package com.example.myclient;



import com.example.myservice.IBinderPool;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;

import androidx.core.view.KeyEventDispatcher;

import java.util.concurrent.CountDownLatch;

public class BinderPool {
    private static final String TAG = "BinderPool";
    public static final int BINDER_NONE = -1;
    public static final int BINDER_COMPUTE = 0;
    public static final int BINDER_SECURITY_CENTER = 1;

    private Context mContext;
    private IBinderPool mBinderPool;
    private static volatile BinderPool sInstance;
    private CountDownLatch mConnectionBinderPoolCountDownLatch;  //线程同步工具
    private static boolean isConnected = false;
    private String mpkgname;
    private String mclasaname;

    private BinderPool(Context context,String pkgname,String clasaname){
        mContext = context.getApplicationContext();
        mpkgname = pkgname;
        mclasaname = clasaname;
        connectBinderPoolService(pkgname,clasaname);   //实例化BidnerPool时就尝试与服务进行连接;
    }

    public boolean getConnectStatus(){
        return isConnected;
    }
    //单例模式
    public static BinderPool getInstance(Context context,String pkgname,String clasaname){
        if (sInstance == null){
            synchronized (BinderPool.class){
                if(sInstance == null){
                    sInstance = new BinderPool(context,pkgname,clasaname);
                }
            }
        }
        return sInstance;
    }


    //服务连接函数
    private synchronized void connectBinderPoolService(String pkgname, String classname){
        Log.d(TAG,"connectBinderPoolService");
        mConnectionBinderPoolCountDownLatch = new CountDownLatch(1);
        //由于要启动指定的服务,这里面采用显示intent的方式
        //通过指定完整的包名、类名,启动指定服务
        //从Android5.0开始 隐式Intent绑定服务的方式已不能使用
        Intent intent = new Intent();
        ComponentName com = new ComponentName(pkgname,classname);
        intent.setComponent(com);
        mContext.bindService(intent,mBinderPoolConnection,Context.BIND_AUTO_CREATE);
        try{
            mConnectionBinderPoolCountDownLatch.await();
        }catch (InterruptedException e){
            e.printStackTrace();
        }
    }

    public synchronized void disconnectBinderPoolService() {
        Log.d(TAG,"disconnectBinderPoolService");
        mConnectionBinderPoolCountDownLatch = new CountDownLatch(1);
        Intent service = new Intent(mContext,BinderPool.class);
        mContext.unbindService(mBinderPoolConnection);
        try{
            mConnectionBinderPoolCountDownLatch.await();
        }catch (InterruptedException e){
            e.printStackTrace();
        }
    }


    public IBinder queryBinder(int binderCode){
        IBinder binder = null;
        try{
            if(mBinderPool != null){
                binder = mBinderPool.queryBinder(binderCode);
            }
        }catch (RemoteException e){
            e.printStackTrace();
        }
        return binder;
    }

    //注意这是在主线程中调用的,所以子线程进行connectBinderPoolService连接时,要等待主线程连接完毕;
    public ServiceConnection mBinderPoolConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.d(TAG,"onServiceConnected");
            isConnected = true;
            mBinderPool = IBinderPool.Stub.asInterface(service);  //在拿到IBinder引用后,通过这个函数获取实例
            try{  //设置死亡代理
                mBinderPool.asBinder().linkToDeath(mBinderPoolDeathRecipient,0);
            }catch (RemoteException e){
                e.printStackTrace();
            }
            mConnectionBinderPoolCountDownLatch.countDown();
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.d(TAG,"onServiceDisconnected");
            isConnected = false;
            mConnectionBinderPoolCountDownLatch.countDown();


        }
    };

    //当Binder死亡时,会回调相应函数
    private IBinder.DeathRecipient mBinderPoolDeathRecipient = new IBinder.DeathRecipient(){
        @Override
        public void binderDied(){
            Log.d(TAG,"binder died.");
            mBinderPool.asBinder().unlinkToDeath(mBinderPoolDeathRecipient,0);
            mBinderPool = null;
            connectBinderPoolService(mpkgname,mclasaname);   //重新尝试连接
        }
    };
}

 

 

 

 

MainActivity.java

 

package com.example.myclient;


import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import com.example.myservice.ICompute;
import com.example.myservice.ISecurityCenter;


public class MainActivity extends AppCompatActivity implements View.OnClickListener{
    private static final String TAG = "MainActivity";
    private String pkgname = "com.example.myservice";
    private String classname = "com.example.myservice.BinderPoolService";
    ISecurityCenter mSecurityCenter;
    ICompute mCompute;
    BinderPool mBinderPool;
    Button btn_conn;
    Button btn_disconn;
    Button btn_compute;
    Button btn_encrypt;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btn_compute = findViewById(R.id.compute);
        btn_encrypt = findViewById(R.id.encrypt);
        btn_conn = findViewById(R.id.conn);
        btn_disconn = findViewById(R.id.disconn);
        btn_compute.setOnClickListener(this);
        btn_encrypt.setOnClickListener(this);
        btn_conn.setOnClickListener(this);
        btn_disconn.setOnClickListener(this);
        Log.d(TAG,"onCreate");

    }

    @Override
    public void onClick(View v){
        switch (v.getId()){
            case R.id.conn:{
                Log.d(TAG,"onClick R.id.conn");
                new Thread(new Runnable(){
                    @Override
                    public void run(){
                        //新建一个线程来进行与Service连接
                        //实例化BinderPool时,就会尝试与服务进行连接
                        mBinderPool = BinderPool.getInstance(MainActivity.this,pkgname,classname);
                    }
                }).start();
                break;
            }

            case R.id.disconn:{
                Log.d(TAG,"onClick R.id.disconn");
                //todo
                break;
            }

            case R.id.compute:{
                Log.d(TAG,"onClick R.id.compute");
                visitICompute();
                break;
            }

            case R.id.encrypt:{
                Log.d(TAG,"onClick R.id.encrypt");
                visitISecurityCenter();
                break;
            }
            default:
                break;
        }
    }


    private void visitISecurityCenter(){
        if(mBinderPool.getConnectStatus() && mSecurityCenter == null){
            IBinder securityBinder = mBinderPool.queryBinder(BinderPool.BINDER_SECURITY_CENTER);
            mSecurityCenter = ISecurityCenter.Stub.asInterface(securityBinder); //获得bindery引用后,实例化对象
            Log.d(TAG,"visit ISecurityCenter");
            String msg = "helloworld-Android";
            Log.d(TAG,"content: "+msg);
            try{
                String password = mSecurityCenter.encrypt(msg);
                Toast.makeText(this,"encrypt: "+password, Toast.LENGTH_SHORT).show();
                Log.d(TAG,"encrypt: "+password);
            }catch (RemoteException e){
                e.printStackTrace();
            }
        }


    }

    private void visitICompute(){
        if(mBinderPool.getConnectStatus() && mCompute == null){
            IBinder computeBinder = mBinderPool.queryBinder(BinderPool.BINDER_COMPUTE);
            mCompute = ICompute.Stub.asInterface(computeBinder); //获得bindery引用后,实例化对象
            Log.d(TAG,"visit ICompute");
            try{
                int result = mCompute.add(3,5);
                Toast.makeText(this,"compute result: "+result, Toast.LENGTH_SHORT).show();
                Log.d(TAG,"encrypt: "+result);
            }catch (RemoteException e){
                e.printStackTrace();
            }
        }
    }
}

 

 

 

 

 

 

=====================================================

目前代码还有点问题,需要进一步调试


import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;

public class BinderPoolService extends Service {
private static final String TAG = "BinderPoolService";

private Binder mBinderPool = new BinderPoolImpl();

public BinderPoolService() {
}

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

@Override
public IBinder onBind(Intent intent) {
Log.d(TAG,"onBind");
return mBinderPool;
}

@Override
public void onDestroy(){
super.onDestroy();
}
}
posted @ 2020-03-13 23:32  Grooovvve  阅读(131)  评论(0编辑  收藏  举报