투케이2K

306. (AndroidStudio/android/java) BluetoothLeAdvertiser 사용해 블루투스 신호 활성 및 서비스 UUID 설정 실시 본문

Android

306. (AndroidStudio/android/java) BluetoothLeAdvertiser 사용해 블루투스 신호 활성 및 서비스 UUID 설정 실시

투케이2K 2022. 7. 6. 12:35
반응형

[개발 환경 설정]

개발 툴 : AndroidStudio

개발 언어 : java

 

[요약 설명]

    /**
     * // ------------------------------------------
     * [블루투스 신호 활성 필요 사항]
     * // ------------------------------------------
     * 1. 퍼미션 권한 부여 실시 :
     *
     * <uses-permission android:name="android.permission.BLUETOOTH"/>
     * <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
     * <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
     * <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
     * <uses-feature android:name="android.hardware.bluetooth_le" />
     * // ------------------------------------------
     * 2. 디바이스 블루투스 및 위치 권한 활성 상태 필요
     * // ------------------------------------------
     * 3. 로직 설명 :
     *   - 블루투스 및 위치 권한 퍼미션 요청
     *   - 블루투스 및 위치 기능 활성 상태 체크
     *   - 블루투스 Advertising 신호 활성 가능한 디바이스 인지 확인 실시
     *   - 디바이스 블루투스 신호 활성 시작
     * // ------------------------------------------
     * 4. 참고 사이트 :
     *   - https://developer.android.com/reference/android/bluetooth/le/AdvertiseSettings
     *   - https://developer.android.com/reference/android/bluetooth/le/AdvertiseData.Builder
     *   - https://developer.android.com/reference/android/bluetooth/le/AdvertiseCallback
     * // ------------------------------------------
     * */
 

[블루투스 신호 활성 소스 코드]

    // [1] : [클래스 전역 변수 선언]
    String ble_uuid = "ffffffff-0000-1111-2222-cccccccccccc";
    BluetoothAdapter bluetoothAdapter = null;
    BluetoothLeAdvertiser advertiser = null;





    // [2] : [블루투스 신호 활성 시작]
    if (C_StateCheck.getBleGpsStateCheck(A_BluetoothAdvertising.this) == true) {

        // [블루투스 신호 활성 시작]
        bluetoothAdvertisingStart();
    }
    else {

        // [팝업창 알림 활성]
        C_Ui_View.showAlert(
                A_BluetoothAdvertising.this, 0,
                "[알림]",
                "블루투스 및 위치 권한을 활성해주세요.",
                "확인", "", ""
        );
    }





    //[3] : [블루투스 신호 활성 시작 메소드 정의]
    public void bluetoothAdvertisingStart(){
        Log.i("---", "---");
        Log.w("//===========//", "================================================");
        Log.i("", "\n" + "[A_BluetoothAdvertising > bluetoothAdvertisingStart() 메소드 : 블루투스 신호 활성 시작]");
        Log.i("", "\n" + "[UUID : "+String.valueOf(ble_uuid)+"]");
        Log.w("//===========//", "================================================");
        Log.i("---", "---");
        try {
            // [블루투스 신호 활성 가능한 디바이스 인지 확인]
            bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
            advertiser = BluetoothAdapter.getDefaultAdapter().getBluetoothLeAdvertiser();

            if (bluetoothAdapter != null && bluetoothAdapter.isMultipleAdvertisementSupported()){

                // [블루투스 신호 활성 데이터 설정]
                ParcelUuid pUuid = new ParcelUuid(UUID.fromString(ble_uuid));
                AdvertiseData ad_data = new AdvertiseData.Builder()
                        .setIncludeDeviceName(false) // [addServiceUuid 31 byte 제한 해제 설정]
                        .addServiceUuid(pUuid) // TODO [서비스 UUID 설정 : 서비스 DATA 와 중복 설정 불가능]
                        //.addServiceData(pUuid, "Data".getBytes("UTF-8")) // TODO [서비스 DATA 설정 : 서비스 UUID 와 중복 설정 불가능]
                        .build();

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

                // [블루투스 신호 활성 시작]
                advertiser.startAdvertising(ad_settings, ad_data, advertiseCallback);
            }
            else {
                // [팝업창 알림 활성]
                C_Ui_View.showAlert(
                        A_BluetoothAdvertising.this, 0,
                        "[알림]",
                        "블루투스 신호 활성을 할 수 없는 디바이스 입니다.",
                        "확인", "", ""
                );
            }
        }
        catch (Exception e){
            e.printStackTrace();
        }
    }





    // [4] : [블루투스 신호 활성 종료 메소드 정의]
    public void bluetoothAdvertisingStop(){
        Log.i("---", "---");
        Log.e("//===========//", "================================================");
        Log.i("", "\n" + "[A_BluetoothAdvertising > bluetoothAdvertisingStop() 메소드 : 블루투스 신호 활성 종료]");
        Log.e("//===========//", "================================================");
        Log.i("---", "---");

        if (advertiser != null){
            advertiser.stopAdvertising(advertiseCallback);
            advertiser = null;
        }

        // [팝업창 알림 활성]
        C_Ui_View.showAlert(
                A_BluetoothAdvertising.this, 0,
                "[알림]",
                "블루투스 신호 활성을 종료 했습니다.",
                "확인", "", ""
        );
    }




    // [5] : [블루투스 신호 활성 상태 확인을 위한 이벤트 리스너 콜백 등록]
    AdvertiseCallback advertiseCallback = new AdvertiseCallback() {
        @Override
        public void onStartSuccess(AdvertiseSettings settingsInEffect) {
            super.onStartSuccess(settingsInEffect);
            Log.i("---", "---");
            Log.w("//===========//", "================================================");
            Log.i("", "\n" + "[A_BluetoothAdvertising > advertiseCallback() 메소드 : 블루투스 신호 활성 상태 감지 확인]");
            Log.i("", "\n" + "[RESULT : "+String.valueOf("SUCCESS")+"]");
            Log.w("//===========//", "================================================");
            Log.i("---", "---");

            // [팝업창 알림 활성]
            C_Ui_View.showAlert(
                    A_BluetoothAdvertising.this, 0,
                    "[알림]",
                    "블루투스 신호 활성을 성공하였습니다. [30 초 신호 활성]",
                    "확인", "", ""
            );
        }

        @Override
        public void onStartFailure(int errorCode) {
            super.onStartFailure(errorCode);
            Log.i("---", "---");
            Log.e("//===========//", "================================================");
            Log.i("", "\n" + "[A_BluetoothAdvertising > advertiseCallback() 메소드 : 블루투스 신호 활성 상태 감지 확인]");
            Log.i("", "\n" + "[RESULT : "+String.valueOf("FAIL")+"]");
            Log.i("", "\n" + "[ERROR : "+String.valueOf(errorCode)+"]");
            Log.e("//===========//", "================================================");
            Log.i("---", "---");

            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;
            }

            // [팝업창 알림 활성]
            C_Ui_View.showAlert(
                    A_BluetoothAdvertising.this, 0,
                    "[알림]",
                    "블루투스 신호 활성을 실패하였습니다. error : " + String.valueOf(errorMessage),
                    "확인", "", ""
            );
        }
    };
 

[블루투스 신호 스캔 예시 소스 코드]

    private ScanCallback leScanCallback = new ScanCallback() {
        @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
        @Override
        public void onScanResult(int callbackType, final ScanResult result) {
            super.onScanResult(callbackType, result);
            final BluetoothDevice device = result.getDevice();

            runOnUiThread(new Runnable() {
                public void run() {
                    Log.d("---","---");
                    Log.d("//===========//","================================================");
                    Log.d("","\n"+"[A_BluetoothScan > leScanCallback() 메소드 : 실시간 BLE 스캔 [롤리팝 이상]]");
                    Log.d("","\n"+"[BLE 스캔 Name] "+" ["+String.valueOf(device.getName())+"]");
                    Log.d("","\n"+"[BLE 스캔 Addr] "+" ["+String.valueOf(device.getAddress())+"]");
                    Log.d("","\n"+"[BLE 스캔 RSSI] "+" ["+String.valueOf(result.getRssi())+"]");
                    Log.d("","\n"+"[BLE 스캔 Record] "+" ["+String.valueOf(result.getScanRecord())+"]");
                    Log.d("//===========//","================================================");
                    Log.d("---","---");

                    //TODO [데이터 조합 실시]
                    try {
                        JSONObject jsonObject = new JSONObject();
                        jsonObject.put("NAME",String.valueOf(device.getName()));
                        jsonObject.put("ADDR",String.valueOf(device.getAddress()));
                        jsonObject.put("UUID",String.valueOf(result.getScanRecord().getServiceUuids()));
                        jsonObject.put("DATA",String.valueOf(result.getScanRecord().getServiceData()));
                        String data = jsonObject.toString();
                        data = data.replaceAll("[,]", "/");
                        if(bleList.contains(data) == false){ //TODO 값을 포함하지 않는 경우만 저장
                            bleList.add(data);
                        }
                    }
                    catch (Exception e){
                        e.printStackTrace();
                    }
                }
            });
        }
    };
 

[신호 활성 - 결과 출력]

 

[신호 스캔 - 결과 출력]

 

 

반응형
Comments