투케이2K

919. (Android/Java) [TargetSdk 33] observableBluetoothAdvertising : 블루투스 실시간 Advertising 광고 신호 활성 본문

Android

919. (Android/Java) [TargetSdk 33] observableBluetoothAdvertising : 블루투스 실시간 Advertising 광고 신호 활성

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

[개발 환경 설정]

개발 툴 : AndroidStudio

개발 언어 : Java / Kotlin

 

[소스 코드]

 

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

- 언어 : Java / Kotlin


- 개발 툴 : AndroidStudio


- 기술 구분 : Bluetooth / Advertising

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






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

    // -----------------------------------------------------------------------------------------
    // TODO [SEARCH FAST] : observableBluetoothAdvertising : 블루투스 실시간 신호 활성 수행
    // -----------------------------------------------------------------------------------------
    // TODO [호출 방법 소스 코드]
    // -----------------------------------------------------------------------------------------
    /*
    try {

        String ble_name = "TWOK-BLUETOOTH";
        String ble_uuid = "ffffffff-0000-1111-2222-cccccccccccc";

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

                        // ------------------------------------------------------------
                        // TODO [실시간 블루투스 신호 활성 성공 처리]
                        // ------------------------------------------------------------
                        if (String.valueOf(value).equals(C_Bluetooth_Module.BLE_ADVERTISING_START)){
                            S_Log.w("BLUE_ADVERTISING", "=================== [Start] : [Bluetooth Advertising] ===================");
                        }

                        // ------------------------------------------------------------
                        // TODO [실시간 블루투스 신호 활성 종료 처리]
                        // ------------------------------------------------------------
                        if (String.valueOf(value).equals(C_Bluetooth_Module.BLE_ADVERTISING_STOP)){
                            S_Log.e("BLUE_ADVERTISING", "=================== [Stop] : [Bluetooth Advertising] ===================");
                        }

                    }
                    @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_FinalMsg.LOG_BUG_STATE, null, e);
    }
    */
    // -----------------------------------------------------------------------------------------
    static BluetoothAdapter ble_advertising_Adapter;
    static String ble_advertising_LOG = "";
    static BluetoothLeAdvertiser ble_Advertiser = null;
    static Handler advertisingHandler = null;

    public static final String BLE_ADVERTISING_START = "BLE_ADVERTISING_START";
    public static final String BLE_ADVERTISING_STOP = "BLE_ADVERTISING_STOP";
    public static final int BLE_ADVERTISING_TIME_OUT = 30;

    public static Observable<String> observableBluetoothAdvertising(Context mContext, String name, String uuid) {

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

            // [변수 초기화]
            ble_advertising_Adapter = null;
            ble_Advertiser = null;
            advertisingHandler = null;
            ble_advertising_LOG = "";

            try {
                // ===============================================================
                S_Log._D_(ACTIVITY_NAME + " :: observableBluetoothAdvertising :: 블루투스 실시간 신호 활성 시작", new String[]{
                        "NAME :: " + String.valueOf(name),
                        "UUID :: " + String.valueOf(uuid)
                });
                // ===============================================================

                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_advertising_LOG = "[ERROR] : Bluetooth Advertising Scan Permission Location Not Granted (블루투스 실시간 신호 활성에 필요한 권한을 확인해주세요. / 위치 권한)";

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

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

                        } else {

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

                            // [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
                                    || ActivityCompat.checkSelfPermission(mContext, Manifest.permission.BLUETOOTH_ADVERTISE) != PackageManager.PERMISSION_GRANTED) {

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

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

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

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

                            // [Input Name, UUID 널 방어 로직 체크]
                            if (C_Util.stringNotNull(name) == false || C_Util.stringNotNull(uuid) == false){

                                // [인풋 데이터 Is Null]
                                ble_advertising_LOG = "[ERROR] : Bluetooth Advertising Name , UUID Is Null (블루투스 실시간 신호 활성에 필요한 NAME , UUID 값을 확인해주세요.)";

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

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

                            }

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

                            // [BluetoothManager 객체 생성]
                            BluetoothManager bluetoothManager = (BluetoothManager) mContext.getSystemService(Context.BLUETOOTH_SERVICE);
                            ble_advertising_Adapter = bluetoothManager.getAdapter();

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

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

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

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

                            }

                            // [블루투스 getBluetoothLeAdvertiser 획득]
                            ble_Advertiser = ble_advertising_Adapter.getBluetoothLeAdvertiser();

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

                            // TODO [isMultipleAdvertisementSupported] : 신호 광고 활성 지원 확인
                            if (ble_advertising_Adapter.isMultipleAdvertisementSupported()) {


                                // TODO [블루투스 신호 활성 이름 설정]
                                ble_advertising_Adapter.setName(name);


                                // TODO [블루투스 신호 활성 UUID 데이터 및 옵션 설정]
                                ParcelUuid pUuid = new ParcelUuid(UUID.fromString(uuid));

                                AdvertiseData ad_data = new AdvertiseData.Builder()
                                        .setIncludeTxPowerLevel(true) // [Tx Power 포함]
                                        .addServiceUuid(pUuid) // [서비스 UUID 설정 : 서비스 DATA 와 중복 설정 불가능]
                                        //.addServiceData(pUuid, "Data".getBytes(StandardCharsets.UTF_8)) // [서비스 DATA 설정]
                                        .build();


                                // TODO [블루투스 신호 활성 정보 설정]
                                AdvertiseSettings ad_settings = new AdvertiseSettings.Builder()
                                        .setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_LOW_LATENCY) // [낮은 대기 시간, 높은 전력 모드에서 Bluetooth LE 광고를 수행]
                                        .setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_HIGH) // [높은 TX 전력 수준을 사용하여 광고]
                                        .setConnectable(true) // [블루투스 연결 설정]
                                        .setTimeout(BLE_ADVERTISING_TIME_OUT * 1000) // [신호 활성 시간]
                                        .build();


                                // TODO [블루투스 스캔 시 표시 되는 이름 표시 여부 설정]
                                AdvertiseData sc_data = new AdvertiseData.Builder()
                                        .setIncludeDeviceName(true) // [기기 이름 포함]
                                        .build();


                                // TODO [블루투스 신호 활성 콜백 응답 리스너 선언]
                                AdvertiseCallback advertiseCallback = new AdvertiseCallback() {
                                    @Override
                                    public void onStartSuccess(AdvertiseSettings settingsInEffect) {
                                        super.onStartSuccess(settingsInEffect);

                                        // [블루투스 정상 신호 활성 로그]

                                        ble_advertising_LOG = "[Success] : Bluetooth Advertising onStartSuccess";

                                        S_Log._W_(ACTIVITY_NAME + " :: observableBluetoothAdvertising :: 블루투스 실시간 신호 활성 수행", new String[]{
                                                "M_LOG :: " + String.valueOf(ble_advertising_LOG),
                                                "NAME :: " + String.valueOf(name),
                                                "UUID :: " + String.valueOf(uuid)
                                        });

                                        // [리턴 반환 실시]
                                        if (subscriber != null && subscriber.isDisposed() == false) {
                                            subscriber.onNext(BLE_ADVERTISING_START);
                                            //subscriber.onComplete(); // TODO [완료 처리는 지정 된 핸들러 타임 아웃 시간 이후 리턴 반환]
                                        }
                                    }

                                    @Override
                                    public void onStartFailure(int errorCode) {
                                        super.onStartFailure(errorCode);

                                        String errorMessage = String.valueOf(errorCode);
                                        switch (errorCode) {
                                            case AdvertiseCallback.ADVERTISE_FAILED_ALREADY_STARTED:
                                                errorMessage += " / " + "ADVERTISE_FAILED_ALREADY_STARTED";
                                                break;
                                            case AdvertiseCallback.ADVERTISE_FAILED_DATA_TOO_LARGE:
                                                errorMessage += " / " + "ADVERTISE_FAILED_DATA_TOO_LARGE";
                                                break;
                                            case AdvertiseCallback.ADVERTISE_FAILED_FEATURE_UNSUPPORTED:
                                                errorMessage += " / " + "ADVERTISE_FAILED_FEATURE_UNSUPPORTED";
                                                break;
                                            case AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR:
                                                errorMessage += " / " + "ADVERTISE_FAILED_INTERNAL_ERROR";
                                                break;
                                            case AdvertiseCallback.ADVERTISE_FAILED_TOO_MANY_ADVERTISERS:
                                                errorMessage += " / " + "ADVERTISE_FAILED_TOO_MANY_ADVERTISERS";
                                                break;
                                        }

                                        // [블루투스가 신호 활성 에러 발생]
                                        ble_advertising_LOG = "[Error] : Bluetooth Advertising onStartFailure (" + String.valueOf(errorMessage) + ")";

                                        S_Log._E_(ACTIVITY_NAME + " :: observableBluetoothAdvertising :: 에러 발생", new String[]{
                                                "M_LOG :: " + String.valueOf(ble_advertising_LOG),
                                                "NAME :: " + String.valueOf(name),
                                                "UUID :: " + String.valueOf(uuid)
                                        });

                                        // [리턴 반환 실시]
                                        if (subscriber != null && subscriber.isDisposed() == false) {
                                            subscriber.onError(new Throwable(ble_advertising_LOG));
                                            subscriber.onComplete(); // TODO [완료 처리는 지정 된 핸들러 타임 아웃 시간 이후 리턴 반환]
                                        }

                                        // [핸들러 종료 처리 수행]
                                        if (advertisingHandler != null) {
                                            try {
                                                advertisingHandler.removeMessages(0);
                                                advertisingHandler.removeCallbacks(null);
                                            } catch (Exception es) {
                                                es.printStackTrace();
                                            }
                                        }
                                    }
                                };


                                // TODO [블루투스 신호 활성 시작] : [콜백 리스너 지정]
                                ble_Advertiser.startAdvertising(ad_settings, ad_data, sc_data, advertiseCallback);


                                // TODO [신호 활성 종료 처리 핸들러 지정]
                                advertisingHandler = new Handler(Looper.getMainLooper());
                                advertisingHandler.postDelayed(new Runnable() {
                                    @Override
                                    public void run() {

                                        // [블루투스가 신호 활성 종료 로그]
                                        ble_advertising_LOG = "[Stop] : Bluetooth Advertising Stop";

                                        S_Log._E_(ACTIVITY_NAME + " :: observableBluetoothAdvertising :: 블루투스 실시간 신호 활성 종료", new String[]{
                                                "M_LOG :: " + String.valueOf(ble_advertising_LOG),
                                                "NAME :: " + String.valueOf(name),
                                                "UUID :: " + String.valueOf(uuid)
                                        });

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

                                        // [블루투스 신호 활성 종료]
                                        if (ble_Advertiser != null) {
                                            if (ActivityCompat.checkSelfPermission(mContext, Manifest.permission.BLUETOOTH_ADVERTISE) != PackageManager.PERMISSION_GRANTED) {
                                                return;
                                            }
                                            ble_Advertiser.stopAdvertising(advertiseCallback);
                                        }
                                    }

                                }, BLE_ADVERTISING_TIME_OUT * 1000);

                            }
                            else {

                                // TODO [블루투스가 활성화 되어 있지 않은 경우 종료]
                                ble_advertising_LOG = "[ERROR] : Bluetooth Advertising Support False (블루투스 신호 광고 활성 지원 확인 필요)";

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

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

                            }

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

                        }

                    }
                }, 0);

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

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

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

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

        });
    }

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






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

D///===========//: ================================================
I/: [LOG :: CLASS PLACE :: C_Bluetooth_Module.lambda$observableBluetoothAdvertising$2(C_Bluetooth_Module.java:628)]
I/: ----------------------------------------------------
I/: [LOG :: DESCRIPTION :: C_Bluetooth_Module :: observableBluetoothAdvertising :: 블루투스 실시간 신호 활성 시작]
I/: ----------------------------------------------------
I/: [LOG :: NAME :: TWOK-BLUETOOTH]
I/: ----------------------------------------------------
I/: [LOG :: UUID :: ffffffff-0000-1111-2222-cccccccccccc]
D///===========//: ================================================


I/BluetoothAdapter: BluetoothAdapter() : com.example.javaproject.staging
D/BluetoothAdapter: getBleEnabledArray(): ON
I/BluetoothAdapter: BLE support array set: [true, true, true, true, true, true, true]


D/BluetoothAdapter: getBleEnabledArray(): ON
I/BluetoothAdapter: setName() : changed to TWOK-BLUETOOTH


I/BluetoothAdapter: BluetoothAdapter() : com.example.javaproject.staging
D/BluetoothAdapter: getBleEnabledArray(): ON
D/BluetoothAdapter: getBleEnabledArray(): ON
D/BluetoothLeAdvertiser: onAdvertisingSetStarted(0, 0, 0)


W///===========//: ================================================
I/: [LOG :: CLASS PLACE :: C_Module.C_Bluetooth_Module$3$1.onStartSuccess(C_Bluetooth_Module.java:738)]
I/: ----------------------------------------------------
I/: [LOG :: DESCRIPTION :: C_Bluetooth_Module :: observableBluetoothAdvertising :: 블루투스 실시간 신호 활성 수행]
I/: ----------------------------------------------------
I/: [LOG :: M_LOG :: [Success] : Bluetooth Advertising onStartSuccess]
I/: ----------------------------------------------------
I/: [LOG :: NAME :: TWOK-BLUETOOTH]
I/: ----------------------------------------------------
I/: [LOG :: UUID :: ffffffff-0000-1111-2222-cccccccccccc]
W///===========//: ================================================

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

 

반응형
Comments