투케이2K

923. (Android/Java) [TargetSdk 33] observableBluetoothLeScanList : 블루투스 LE 실시간 리스트 목록 스캔 수행 본문

Android

923. (Android/Java) [TargetSdk 33] observableBluetoothLeScanList : 블루투스 LE 실시간 리스트 목록 스캔 수행

투케이2K 2024. 12. 24. 20:52

[개발 환경 설정]

개발 툴 : AndroidStudio

개발 언어 : Java / Kotlin

 

[소스 코드]

 

// --------------------------------------------------------------------------------------
[개발 및 테스트 환경]
// --------------------------------------------------------------------------------------

- 언어 : Java / Kotlin


- 개발 툴 : AndroidStudio


- 기술 구분 : Bluetooth / Scan

// --------------------------------------------------------------------------------------






// --------------------------------------------------------------------------------------
[소스 코드]
// --------------------------------------------------------------------------------------

  // -----------------------------------------------------------------
  // TODO [SEARCH FAST] : observableBluetoothLeScanList : 블루투스 실시간 목록 스캔 결과 반환
  // -----------------------------------------------------------------
  // TODO [호출 방법 소스 코드]
  // -----------------------------------------------------------------
  /*
  try {

      C_Bluetooth_Module.observableBluetoothLeScanList(A_Intro.this)
              .subscribeOn(AndroidSchedulers.mainThread()) // [Observable (생성자) 로직을 IO 스레드에서 실행 : 백그라운드]
              .observeOn(Schedulers.io()) // [Observer (관찰자) 로직을 메인 스레드에서 실행]
              .subscribe(new Observer<ArrayList>() { // [Observable.create 타입 지정]
                  @Override
                  public void onSubscribe(@NonNull Disposable d) {
                  }
                  @Override
                  public void onNext(@NonNull ArrayList value) {
                      S_Log._W_(ACTIVITY_NAME + " :: 블루투스 실시간 스캔 :: onNext", new String[]{String.valueOf(value)});
                  }
                  @Override
                  public void onError(@NonNull Throwable e) {
                      S_Log._E_(ACTIVITY_NAME + " :: 블루투스 실시간 스캔 :: onError", new String[]{String.valueOf(e.getMessage())});
                  }
                  @Override
                  public void onComplete() {
                  }
              });

  } catch (Exception e) {
      S_Log._printStackTrace_(mContext, S_FinalData.LOG_BUG_STATE, null, e);
  }
  */
  // -----------------------------------------------------------------

  // [필요 변수 선언]
  static BluetoothAdapter ble_Le_Adapter;
  static int ble_Le_COUNT = 0;
  static String ble_Le_LOG = "";
  static ArrayList ble_Le_List = null;
  public static final int blue_Le_TimeOut = 10;

  // -----------------------------------------------------------------

  public static Observable<ArrayList> observableBluetoothLeScanList(Context mContext) {

      // [로직 처리 실시]
      return Observable.create(subscriber -> {

          // [변수 초기화]
          ble_Le_Adapter = null;
          ble_Le_COUNT = 0;
          ble_Le_LOG = "";
          ble_Le_List = null;

          try {
              // ===============================================================
              S_Log._D_(ACTIVITY_NAME + " :: observableBluetoothLeScanList :: 블루투스 실시간 목록 리스트 스캔 시작", null);
              // ===============================================================

              new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
                  @Override
                  public void run() {

                      // [퍼미션 권한 체크 실시]
                      if (ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED
                              || ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {

                          // [퍼미션이 부여되어있지 않은 경우 종료]
                          ble_Le_LOG = "[ERROR] : Bluetooth Le Scan Permission Location Not Granted (블루투스 실시간 목록 스캔에 필요한 권한을 확인해주세요. / 위치 권한)";

                          S_Log._E_(ACTIVITY_NAME + " :: observableBluetoothLeScanList :: 에러 발생", new String[]{String.valueOf(ble_Le_LOG)});

                          // [리턴 반환 실시]
                          if (subscriber != null && subscriber.isDisposed() == false) {
                              subscriber.onError(new Throwable(ble_Le_LOG));
                              subscriber.onComplete();
                          }
                          return;

                      } else {

                          // ---------------------------------------------------------------

                          // TODO [Android 12 이상 권한 체크 방어 로직]

                          if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S
                                  && ActivityCompat.checkSelfPermission(mContext, Manifest.permission.BLUETOOTH_SCAN) != PackageManager.PERMISSION_GRANTED
                                  || ActivityCompat.checkSelfPermission(mContext, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) {

                              // [퍼미션이 부여되어있지 않은 경우 종료]
                              ble_Le_LOG = "[ERROR] : Bluetooth Le Scan Permission Bluetooth Scan Or Connect Not Granted (블루투스 실시간 목록 스캔에 필요한 권한을 확인해주세요. / 블루투스 스캔 및 연결 권한)";

                              S_Log._E_(ACTIVITY_NAME + " :: observableBluetoothLeScanList :: 에러 발생", new String[]{String.valueOf(ble_Le_LOG)});

                              // [리턴 반환 실시]
                              if (subscriber != null && subscriber.isDisposed() == false) {
                                  subscriber.onError(new Throwable(ble_Le_LOG));
                                  subscriber.onComplete();
                              }
                              return;
                          }

                          // ---------------------------------------------------------------

                          // [블루투스 페어링 목록 리스트 스캔 실시]
                          BluetoothManager bluetoothManager = (BluetoothManager) mContext.getSystemService(Context.BLUETOOTH_SERVICE);
                          ble_Le_Adapter = bluetoothManager.getAdapter();

                          if (ble_Le_Adapter == null || ble_Le_Adapter.isEnabled() == false) {

                              // [블루투스가 활성화 되어 있지 않은 경우 종료]
                              ble_Le_LOG = "[ERROR] : Bluetooth Adapter Is Null Or Enabled False (블루투스 기능 지원 여부 및 블루투스 기능 활성 상태 확인 필요)";

                              S_Log._E_(ACTIVITY_NAME + " :: observableBluetoothLeScanList :: 에러 발생", new String[]{String.valueOf(ble_Le_LOG)});

                              // [리턴 반환 실시]
                              if (subscriber != null && subscriber.isDisposed() == false) {
                                  subscriber.onError(new Throwable(ble_Le_LOG));
                                  subscriber.onComplete();
                              }
                              return;

                          }

                          BluetoothLeScanner bluetoothLeScanner = ble_Le_Adapter.getBluetoothLeScanner();
                          ble_Le_List = new ArrayList<>(); // [리스트 객체 초기화]

                          // ---------------------------------------------------------------

                          // [블루투스 리스트 스캔 콜백 함수 정의]
                          ScanCallback scanCallback = new ScanCallback() {

                              // TODO [BLE 광고가 발견되면 콜백합니다.]
                              @Override
                              public void onScanResult(int callbackType, ScanResult result) {
                                  BluetoothDevice device = result.getDevice();
                                  S_Log.w("BLE_SCAN", device.toString());

                                  HashMap<String, Object> map = new HashMap<>();
                                  map.put("address", device.getAddress());

                                  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
                                      if (ActivityCompat.checkSelfPermission(mContext, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) {
                                          return;
                                      }
                                      map.put("alias", device.getAlias());
                                  }

                                  map.put("name", device.getName());
                                  map.put("bondState", device.getBondState());
                                  map.put("type", device.getType());
                                  map.put("uuid", device.getUuids());

                                  // [리스트에 추가]
                                  ble_Le_List.add(map);
                              }

                              // TODO [일괄 처리 결과가 전달될 때 콜백합니다.]
                              @Override
                              public void onBatchScanResults(List<ScanResult> results) {
                                  for (ScanResult result : results) {
                                      BluetoothDevice device = result.getDevice();
                                      S_Log.w("BLE_BATCH", device.toString());

                                      HashMap<String, Object> map = new HashMap<>();
                                      map.put("address", device.getAddress());

                                      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
                                          if (ActivityCompat.checkSelfPermission(mContext, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) {
                                              return;
                                          }
                                          map.put("alias", device.getAlias());
                                      }

                                      map.put("name", device.getName());
                                      map.put("bondState", device.getBondState());
                                      map.put("type", device.getType());
                                      map.put("uuid", device.getUuids());

                                      // [리스트에 추가]
                                      ble_Le_List.add(map);

                                  }
                              }

                              // TODO [스캔을 시작할 수 없을 때 콜백합니다.]
                              @Override
                              public void onScanFailed(int errorCode) {
                                  ble_Le_LOG = "[Error] : Bluetooth onScanFailed ErrorCode (" + String.valueOf(errorCode) + ")";

                                  S_Log._E_(ACTIVITY_NAME + " :: observableBluetoothLeScanList :: 에러 발생", new String[]{String.valueOf(ble_Le_LOG)});
                              }
                          };

                          // ---------------------------------------------------------------

                          // TODO [블루투스 리스트 스캔 시작]
                          bluetoothLeScanner.startScan(scanCallback);

                          // ---------------------------------------------------------------

                          // TODO [블루투스 리스트 스캔 타임 아웃 핸들러 지정]
                          Handler handler = new Handler(Looper.getMainLooper());
                          handler.postDelayed(new Runnable() {
                              @Override
                              public void run() {

                                  // [로그 추가]
                                  if (C_Util.stringNotNull(ble_Le_LOG) == false) { // TODO [에러가 발생하지 않은 경우]
                                      ble_Le_LOG = "[Success] : Bluetooth Le List Scan";
                                  }

                                  S_Log._W_(ACTIVITY_NAME + " :: observableBluetoothLeScanList :: 블루투스 실시간 리스트 목록 스캔", new String[]{
                                          "M_LOG :: " + String.valueOf(ble_Le_LOG),
                                          "SCAN_COUNT :: " + String.valueOf(ble_Le_List.size()),
                                          "SCAN_LIST :: " + String.valueOf(ble_Le_List)
                                  });

                                  // [리턴 반환 실시]
                                  if (subscriber != null && subscriber.isDisposed() == false) {
                                      subscriber.onNext(ble_Le_List);
                                      subscriber.onComplete();
                                  }

                                  if (ActivityCompat.checkSelfPermission(mContext, Manifest.permission.BLUETOOTH_SCAN) != PackageManager.PERMISSION_GRANTED) {
                                      return;
                                  }

                                  // TODO [블루투스 리스트 스캔 종료]
                                  bluetoothLeScanner.stopScan(scanCallback);
                              }

                          }, blue_Le_TimeOut * 1000);

                          // ---------------------------------------------------------------

                      }

                  }
              }, 0);

          } catch (final Exception e) {
              S_Log._printStackTrace_(mContext, S_FinalData.LOG_BUG_STATE, null, e);

              S_Log._E_(ACTIVITY_NAME + " :: observableBluetoothLeScanList :: EXCEPTION", new String[]{String.valueOf(e.getMessage())});

              try {
                  // [에러 메시지 삽입]
                  ble_Le_LOG = "[EXCEPTION] : " + String.valueOf(e.getMessage());

                  // [리턴 반환 실시]
                  if (subscriber != null && subscriber.isDisposed() == false) {
                      subscriber.onError(new Throwable(ble_Le_LOG));
                      subscriber.onComplete();
                  }
              } catch (Exception ex) {
                  ex.printStackTrace();
              }
          }

      });
  }

// --------------------------------------------------------------------------------------






// --------------------------------------------------------------------------------------
[결과 출력]
// --------------------------------------------------------------------------------------

W///===========//: ================================================
I/: [LOG :: CLASS PLACE :: com.example.javaproject.A_Intro$1$1.onNext(A_Intro.java:361)]
I/: ----------------------------------------------------
I/: [LOG :: DESCRIPTION :: A_Intro :: 블루투스 실시간 스캔 :: onNext]
I/: ----------------------------------------------------
I/: [LOG :: [{bondState=10, address=39:7F:19:2D:DC:4D, name=null, alias=null, type=0, uuid=null}, {bondState=10, address=43:C3:42:92:6E:40, name=null, alias=null, type=0, uuid=null}]]
W///===========//: ================================================

// --------------------------------------------------------------------------------------

 

반응형
Comments