content: package com.allenliu.classicbt;
  
  import android.app.Notification;
  import android.bluetooth.BluetoothA2dp;
  import android.bluetooth.BluetoothAdapter;
  import android.bluetooth.BluetoothDevice;
  import android.content.Context;
  import android.content.Intent;
  import android.content.IntentFilter;
  import android.os.Build;
  import android.os.Handler;
  import android.os.Looper;
  import com.allenliu.classicbt.listener.*;
  import com.allenliu.classicbt.scan.ScanConfig;
  import com.allenliu.classicbt.scan.ScanTimer;
  
  import java.lang.reflect.Method;
  import java.util.Set;
  
  /**
   * @author AllenLiu
   * @version 1.0
   * @date 2019/5/8
   */
  public class BleManager implements BleFunction {
      private BluetoothAdapter mBluetoothAdapter;
      private Context application;
      private ScanResultListener resultListener;
  
      private ScanTimer scanTimer;
      // Create a BroadcastReceiver for ACTION_FOUND
      private boolean isRegister = false;
  
  
      private BtReceiver mReceiver;
      private String uuid;
      private Notification notification;
      private boolean isForegroundService = false;
      private ConnectResultlistner clientConnectResultListener;
      private ConnectResultlistner serverConnectResultListener;
  
      public static BleManager getInstance() {
          return Holder.client;
      }
  
      static class Holder {
          static BleManager client = new BleManager();
      }
  
      public BleManager() {
          mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
      }
  
      public ConnectResultlistner getClientConnectResultListener() {
          return clientConnectResultListener;
      }
  
      public void setClientConnectResultListener(ConnectResultlistner clientConnectResultListener) {
          this.clientConnectResultListener = clientConnectResultListener;
          mReceiver.setClientConnectResultListener(clientConnectResultListener);
  
      }
  
      public ConnectResultlistner getServerConnectResultListener() {
          return serverConnectResultListener;
      }
  
      @Override
      public void init(Context context) {
          application = context;
          mReceiver = new BtReceiver();
          registerReceiver();
  
  
      }
  
      @Override
      public void setConnectionUUID(String uuid) {
          this.uuid = uuid;
  
      }
  
  
      private void registerReceiver() {
          if (resultListener != null)
              mReceiver.setScanResultListener(resultListener);
  //        if(pinResultListener!=null)
  //            mReceiver.setPinResultListener(pinResultListener);
  //        if(cancelPinResultListener!=null)
  //            mReceiver.setCancelPinResultListener(cancelPinResultListener);
          if (clientConnectResultListener != null)
              mReceiver.setClientConnectResultListener(clientConnectResultListener);
          if (serverConnectResultListener != null)
              mReceiver.setServerConnectResultListener(serverConnectResultListener);
          if (!isRegister) {
              isRegister = true;
              // Register the BroadcastReceiver
              IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
              filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);//状态改变
              filter.addAction(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);//行动扫描模式改变了
              filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);//动作状态发生了变化
              filter.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED);
              filter.addAction(BluetoothDevice.ACTION_PAIRING_REQUEST);
              filter.addAction(BluetoothA2dp.ACTION_PLAYING_STATE_CHANGED);
              //<action android:name="android.bluetooth.device.action.ACL_CONNECTED" />
              //    <action android:name="android.bluetooth.device.action.ACL_DISCONNECT_REQUESTED" />
              //    <action android:name="android.bluetooth.device.action.ACL_DISCONNECTED" />
              filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED);
              filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
              application.registerReceiver(mReceiver, filter); // Don't forget to unregister during onDestroy
          }
      }
  
      @Override
      public void setResultListener(ScanResultListener resultListener) {
          this.resultListener = resultListener;
      }
  
      @Override
      public boolean isSupported() {
          return mBluetoothAdapter != null;
      }
  
      @Override
      public Set<BluetoothDevice> getPairedDevices() {
          return mBluetoothAdapter.getBondedDevices();
  
      }
  
      @Override
      public void scan(ScanConfig scanConfig, ScanResultListener scanResultListener) {
          if (scanTimer != null) {
              scanTimer.cancel();
          }
          scanTimer = new ScanTimer(scanConfig) {
              @Override
              public void onFinish() {
                  stopSearch();
              }
          };
          scanTimer.start();
          this.resultListener = scanResultListener;
  
          registerReceiver();
          boolean r = mBluetoothAdapter.startDiscovery();
          if (!r && resultListener != null) {
              resultListener.onError();
              resultListener.onFinish();
          }
  
      }
  
      @Override
      public void stopSearch() {
          if (isRegister) {
  //            application.unregisterReceiver(mReceiver);
              isRegister = false;
  
              if (resultListener != null) {
                  new Handler(Looper.getMainLooper()).post(() -> {
                      resultListener.onFinish();
                  });
              }
          }
          if (mBluetoothAdapter.isDiscovering())
              mBluetoothAdapter.cancelDiscovery();
          if (scanTimer != null) {
              scanTimer.cancel();
          }
  
      }
  
      @Override
      public void connect(BluetoothDevice device, ConnectResultlistner c) {
          this.clientConnectResultListener = c;
          ConnectService.start(application, device, ConnectThread.CLIENT, uuid, isForegroundService, notification);
          mReceiver.setClientConnectResultListener(clientConnectResultListener);
  
  
      }
  
      @Override
      public void destory() {
  //        application.unregisterReceiver(mReceiver);
          stopSearch();
          application.stopService(new Intent(application, ConnectService.class));
      }
  
      @Override
      public void pin(BluetoothDevice device, PinResultListener resultListener) {
          if (device == null) {
              return;
          }
          mReceiver.setPinResultListener(resultListener);
          if (device.getBondState() == BluetoothDevice.BOND_NONE) {
              if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                  device.createBond();
              } else {
                  try {
                      Method method = device.getClass().getMethod("createBond");
                      method.invoke(device);
                  } catch (Exception e) {
                      e.printStackTrace();
                      resultListener.pairFailed(device);
                  }
              }
          }
      }
  
      @Override
      public void cancelPin(BluetoothDevice device, ResultListener resultListener) {
          if (device == null) {
              return;
          }
          mReceiver.setCancelPinResultListener(resultListener);
  
          if (device.getBondState() != BluetoothDevice.BOND_NONE) {
              try {
                  Method method = device.getClass().getMethod("removeBond");
                  boolean r = (boolean) method.invoke(device);
              } catch (Exception e) {
                  e.printStackTrace();
                  resultListener.failed(e);
              }
          }
      }
  
      @Override
      public void setServerConnectResultListener(ConnectResultlistner connectResultListener) {
          this.serverConnectResultListener = connectResultListener;
          mReceiver.setServerConnectResultListener(serverConnectResultListener);
  
  //        if (serverConnectThread != null)
  //            serverConnectThread.setConnectResultlistner(connectResultListener);
      }
  
      @Override
      public void registerServerConnection(ConnectResultlistner connectResultListener) {
          this.serverConnectResultListener = connectResultListener;
          ConnectService.start(application, null, ConnectThread.SERVER, uuid, isForegroundService, notification);
          mReceiver.setServerConnectResultListener(serverConnectResultListener);
  
      }
  
      @Override
      public void setForegroundService(boolean foregroundService) {
          this.isForegroundService = foregroundService;
      }
  
      @Override
      public void setNotification(Notification notification) {
          this.notification = notification;
      }
  
      @Override
      public void enableDiscoverable(long time) {
          Intent discoverableIntent = new
                  Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
          discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, time);
          discoverableIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
          application.startActivity(discoverableIntent);
      }
  
  
  }
  