Andoird进程间通讯Binder相关内容

2019-04-04  本文已影响0人  Android_小马范儿
   <service
           android:name=".bind.BookManagerService"
           android:process=":remote"/>

服务端Binder意外死亡,客户端需要重启操作;

  private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
        @Override
        public void binderDied() {
            restartServer(); //服务端意外死亡后重新连接的方式在客户端的Binder线程中
        }
    };

   private void restartServer() {
        Log.e(TAG, "mDeathRecipient-->binderDied-->");
        if (mBookBinder == null) {
            return;
        }
        mBookBinder.asBinder().unlinkToDeath(mDeathRecipient, 0);
        mBookBinder = null;
        Log.e(TAG, "mDeathRecipient-->bindService");
        startBookService();
    }
  private void startBookService() {
        Intent intent = new Intent(this, BookManagerService.class);
        bindService(intent, connection, BIND_AUTO_CREATE);
    }

    private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
//            mBankBinder= IBankAIDL.Stub.asInterface(service);
            mBookBinder = IBookManager.Stub.asInterface(service);
            try {
                service.linkToDeath(mDeathRecipient, 0);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
      
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.e(TAG, "onServiceDisconnected-->binder died");
//            restartServer();    //服务端意外死亡后重新连接的方式在UI线程
        }
    };

权限校验,用来校验客户端的Binder

  1. 首先在服务端定义权限并且检查权限
   在服务端清单中定义
  <permission
    android:name="com.xiaoma.brick.permission.ACCESS_BOOK_SERVICE"
        android:protectionLevel="normal" />
 
在服务端的service中检查
   @Override
    public IBinder onBind(Intent intent) {
        int check = checkCallingOrSelfPermission("com.xiaoma.brick.permission.ACCESS_BOOK_SERVICE");
        Log.e(TAG, "onBind: "+check);
        if(check==PackageManager.PERMISSION_DENIED){
            Log.e(TAG, "onBind: 权限校验呢");
            return null;
        }
        return mBinder;
    }
  1. 在客户端增加权限
在客户端清单文件增加权限,通服务端保持一致
 <uses-permission android:name="com.xiaoma.brick.permission.ACCESS_BOOK_SERVICE" />
  1. 如果应用内存在多个跨进程通过,存在多个服务的情况下,使用进程池服务统一处理;防止过多的跨进程服务
package com.xiaoma.brick.aidl;

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

interface IBinderPool {
    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */

     IBinder queryBinder(int binderCode);
}

//跨进程服务使用线程池的话,就可以通过单例处理,保证唯一的

package com.xiaoma.brick.bind.impl;

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

import com.xiaoma.brick.aidl.IBinderPool;

import java.util.concurrent.CountDownLatch;

public class BinderPool {


    private final Context mContext;
    private IBinderPool mBinderPool;
    private static volatile BinderPool mInstance;
    private CountDownLatch mCountDownLatch;
    public static final int BINDER_BANK = 100;
    public static final int BINDER_BOOK = 101;

    private BinderPool(Context context) {
        mContext = context.getApplicationContext();
        connectBinderPoolService();
    }

    public static BinderPool getInstance(Context context) {
        if (mInstance == null) {
            synchronized (BinderPool.class) {
                if (mInstance == null) {
                    mInstance = new BinderPool(context);
                }
            }
        }
        return mInstance;
    }


    private synchronized void connectBinderPoolService() {
        mCountDownLatch = new CountDownLatch(1);
        Intent service = new Intent(mContext, BinderPoolService.class);
        mContext.bindService(service, mBinderPoolConnection, mContext.BIND_AUTO_CREATE);
        try {
            mCountDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private ServiceConnection mBinderPoolConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mBinderPool = IBinderPool.Stub.asInterface(service);
            try {
                mBinderPool.asBinder().linkToDeath(mBinderPoolDeathRecipient, 0);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
            try {
                mCountDownLatch.countDown();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };

    private IBinder.DeathRecipient mBinderPoolDeathRecipient = new IBinder.DeathRecipient() {
        @Override
        public void binderDied() {
            mBinderPool.asBinder().unlinkToDeath(mBinderPoolDeathRecipient, 0);
            mBinderPool = null;
            connectBinderPoolService();
        }
    };


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

        return binder;
    }


    public static class BinderPollImpl extends IBinderPool.Stub {

        public BinderPollImpl() {
            super();
        }

        @Override
        public IBinder queryBinder(int binderCode) throws RemoteException {
            IBinder binder = null;
            switch (binderCode) {
                case BINDER_BANK:
                    binder = new BankBinderImpl();
                    break;
                case BINDER_BOOK:
                    binder = new BookBinderImpl();
                    break;
                default:
                    break;
            }
            return binder;
        }
    }
}

  1. RemoteCallbackList是系统专门提供的用于处理跨进程listener的接口
 private RemoteCallbackList<IOnNewBookArrivedListener> mListenerList = new RemoteCallbackList<>();
//遍历listener集合
 int N = mListenerList.beginBroadcast();
        Log.e("xiaoma", "onNewBookedArrived ,notify listeners" +N);
        for (int i = 0; i <N; i++) {
            IOnNewBookArrivedListener iOnNewBookArrivedListener = mListenerList.getBroadcastItem(i);
            Log.e("xiaoma", "onNewBookedArrived ,notify listeners" + iOnNewBookArrivedListener);
            iOnNewBookArrivedListener.onNewBookArrived(book);
        }
        mListenerList.finishBroadcast();
  1. 多个客户端同事连接服务器的时候需要处理并发的情况,所以在AIDL方法中处理同步,直接使用CopyOnWriteArrayList来进行自动的线程同步
上一篇下一篇

猜你喜欢

热点阅读