• 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();
    }
    }
  • 相关阅读:
    内联元素和块元素
    inline-block
    overflow:hidden
    鼠标点到某个位置出现手势的效果。
    对于清浮动问题,终极。
    将所需要的图标排成一列组成一张图片,方便管理。li的妙用
    异步错误处理 -- 时机
    错误传播 --try{}catch(e){console.log(e)}
    js
    jquery源码学习-2-选择器
  • 原文地址:https://www.cnblogs.com/grooovvve/p/12489894.html
Copyright © 2020-2023  润新知