Notice
Recent Posts
Recent Comments
Link
투케이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///===========//: ================================================
// --------------------------------------------------------------------------------------
반응형
'Android' 카테고리의 다른 글
Comments