Notice
Recent Posts
Recent Comments
Link
투케이2K
921. (Android/Java) [TargetSdk 33] observableBeaconScanList : Altbeacon 실시간 비콘 신호 활성 Advertising 코드 본문
Android
921. (Android/Java) [TargetSdk 33] observableBeaconScanList : Altbeacon 실시간 비콘 신호 활성 Advertising 코드
투케이2K 2024. 12. 24. 17:35[개발 환경 설정]
개발 툴 : AndroidStudio
개발 언어 : Java / Kotlin
[소스 코드]
// --------------------------------------------------------------------------------------
[개발 및 테스트 환경]
// --------------------------------------------------------------------------------------
- 언어 : Java / Kotlin
- 개발 툴 : AndroidStudio
- 기술 구분 : Bluetooth / Beacon / Advertising
// --------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------
[사전) 라이브러리 의존성 설정 및 퍼미션 권한 설정 정리]
// --------------------------------------------------------------------------------------
/**
* // --------------------------------------------------------
* TODO [클래스 설명]
* // --------------------------------------------------------
* 1. TODO [설명] : 비콘 스캔 및 신호 활성 수행 클래스 : 안드로이드 상위 버전 전용 (S 안드로이드 12 이상)
* // --------------------------------------------------------
* 2. 라이브러리 추가 방법 : Git (https://github.com/AltBeacon/android-beacon-library)
*
* // TODO [altbeacon : 비콘 스캔 및 신호 활성 라이브러리]
* implementation 'org.altbeacon:android-beacon-library:2.19'
* //noinspection GradleCompatible
* implementation 'com.android.support:localbroadcastmanager:28.0.0'
*
* // --------------------------------------------------------
* 3. 필요 퍼미션 권한 : 위치 및 GPS 권한 , 블루투스 권한 - SCAN , ADVERTISE , CONNECT
*
* // TODO [공통]
* <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
* <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
*
* <uses-permission android:name="android.permission.BLUETOOTH"/>
* <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
* <uses-feature android:name="android.hardware.bluetooth_le" />
*
* // TODO [안드로이드 12 이상 : S 버전]
* <uses-permission android:name="android.permission.BLUETOOTH_SCAN"/>
* <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE"/>
* <uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
* // --------------------------------------------------------
* */
// --------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------
[소스 코드]
// --------------------------------------------------------------------------------------
// ----------------------------------------------------------
// TODO [SEARCH FAST] : observableBeaconAdvertising : 비콘 실시간 신호 활성 수행
// ----------------------------------------------------------
// TODO [호출 방법 소스 코드]
// ----------------------------------------------------------
/*
try {
// [비콘 신호 활성에 필요한 변수 선언]
String uuid = "03c3c219-588e-f909-db0a-320ac6deeff0";
int major = 1;
int minor = 36;
// [비콘 신호 활성 수행]
C_Beacon_Client_Module.observableBeaconAdvertising(A_Intro.this, uuid, major, minor)
.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_Beacon_Client_Module.BEACON_ADVERTISING_START)){
S_Log.w("BEACON_ADVERTISING", "=================== [Start] : [Beacon Advertising] ===================");
}
// ------------------------------------------------------------
// TODO [실시간 비콘 신호 활성 종료 처리]
// ------------------------------------------------------------
if (String.valueOf(value).equals(C_Beacon_Client_Module.BEACON_ADVERTISING_STOP)){
S_Log.e("BEACON_ADVERTISING", "=================== [Stop] : [Beacon 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 BeaconTransmitter beaconTransmitter = null;
static BluetoothAdapter ble_advertising_Adapter;
static String beacon_advertising_LOG = "";
static Handler advertisingHandler = null;
public static final String BEACON_ADVERTISING_START = "BEACON_ADVERTISING_START";
public static final String BEACON_ADVERTISING_STOP = "BEACON_ADVERTISING_STOP";
public static final int BEACON_ADVERTISING_TIME_OUT = 30;
// ----------------------------------------------------------
public static Observable<String> observableBeaconAdvertising(Context mContext, String uuid, int major, int minor) {
// [로직 처리 실시]
return Observable.create(subscriber -> {
// [변수 초기화]
beaconTransmitter = null;
ble_advertising_Adapter = null;
advertisingHandler = null;
beacon_advertising_LOG = "";
try {
// ===============================================================
S_Log._D_(ACTIVITY_NAME + " :: observableBeaconAdvertising :: 비콘 실시간 신호 활성 시작", new String[]{
"UUID :: " + String.valueOf(uuid),
"MAJOR :: " + String.valueOf(major),
"NINOR :: " + String.valueOf(minor)
});
// ===============================================================
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) {
// [퍼미션이 부여되어있지 않은 경우 종료]
beacon_advertising_LOG = "[ERROR] : Beacon Advertising Scan Permission Location Not Granted (비콘 실시간 신호 활성에 필요한 권한을 확인해주세요. / 위치 권한)";
S_Log._E_(ACTIVITY_NAME + " :: observableBeaconAdvertising :: 에러 발생", new String[]{String.valueOf(beacon_advertising_LOG)});
// [리턴 반환 실시]
if (subscriber != null && subscriber.isDisposed() == false) {
subscriber.onError(new Throwable(beacon_advertising_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
|| ActivityCompat.checkSelfPermission(mContext, Manifest.permission.BLUETOOTH_ADVERTISE) != PackageManager.PERMISSION_GRANTED) {
// [퍼미션이 부여되어있지 않은 경우 종료]
beacon_advertising_LOG = "[ERROR] : Beacon Advertising Permission Bluetooth Scan Or Connect Or Advertising Not Granted (비콘 실시간 신호 활성에 필요한 권한을 확인해주세요. / 블루투스 스캔 및 연결, 광고 활성 권한)";
S_Log._E_(ACTIVITY_NAME + " :: observableBeaconAdvertising :: 에러 발생", new String[]{String.valueOf(beacon_advertising_LOG)});
// [리턴 반환 실시]
if (subscriber != null && subscriber.isDisposed() == false) {
subscriber.onError(new Throwable(beacon_advertising_LOG));
subscriber.onComplete();
}
return;
}
// ---------------------------------------------------------------
// [Input Name, UUID 널 방어 로직 체크]
if (C_Util.stringNotNull(uuid) == false || minor < 0 || major < 0){
// [인풋 데이터 Is Null]
beacon_advertising_LOG = "[ERROR] : Beacon Advertising Uuid , Major , Minor Is Null (비콘 실시간 신호 활성에 필요한 Uuid , Major , Minor 값을 확인해주세요.)";
S_Log._E_(ACTIVITY_NAME + " :: observableBeaconAdvertising :: 에러 발생", new String[]{String.valueOf(beacon_advertising_LOG)});
// [리턴 반환 실시]
if (subscriber != null && subscriber.isDisposed() == false) {
subscriber.onError(new Throwable(beacon_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) {
// [블루투스가 활성화 되어 있지 않은 경우 종료]
beacon_advertising_LOG = "[ERROR] : Bluetooth Adapter Is Null Or Enabled False (블루투스 기능 지원 여부 및 블루투스 기능 활성 상태 확인 필요)";
S_Log._E_(ACTIVITY_NAME + " :: observableBeaconAdvertising :: 에러 발생", new String[]{String.valueOf(beacon_advertising_LOG)});
// [리턴 반환 실시]
if (subscriber != null && subscriber.isDisposed() == false) {
subscriber.onError(new Throwable(beacon_advertising_LOG));
subscriber.onComplete();
}
return;
}
// ---------------------------------------------------------------
// TODO [isMultipleAdvertisementSupported] : 신호 광고 활성 지원 확인
if (ble_advertising_Adapter.isMultipleAdvertisementSupported()) {
// TODO [Beacon 비콘 신호 활성 정보 생성]
Beacon beacon = new Beacon.Builder()
.setId1(uuid.toLowerCase()) //TODO UUID
.setId2(String.valueOf(major)) // 비콘 major 값 정의 (정수) //TODO Major
.setId3(String.valueOf(minor)) // 비콘 minor 값 정의 (정수) //TODO Minor
.setManufacturer(0x004c) // TODO 아이폰에서도 받을 수 있게 하기 위함 - 아이폰은 지들 제조사하고 ibeacon밖에 스캔못함(안드로이드에서도 받아진다)
.setTxPower(-59) // 전송할 때의 신호 세기 dB (-65보다 -59가 더 큰 신호 즉, -59가 더 가까이있다)
.setDataFields(Arrays.asList(new Long[]{0L}))
.build();
// TODO [Layout 설정] : 아이폰에서도 받을 수 있게 하기 위함 - 아이폰은 지들 제조사하고 ibeacon 밖에 스캔못함 (안드로이드에서도 받아진다)
BeaconParser beaconParser = new BeaconParser().setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24");
//beaconParser.setHardwareAssistManufacturerCodes(new int[]{0x4C00});
// TODO [비콘 신호 활성 종료 처리 핸들러 등록]
advertisingHandler = new Handler(Looper.getMainLooper());
advertisingHandler.postDelayed(new Runnable() {
@Override
public void run() {
// [비콘 신호 활성 종료 로그]
beacon_advertising_LOG = "[Stop] : Beacon Advertising Stop";
S_Log._E_(ACTIVITY_NAME + " :: observableBeaconAdvertising :: 비콘 실시간 신호 활성 종료", new String[]{
"M_LOG :: " + String.valueOf(beacon_advertising_LOG),
"UUID :: " + String.valueOf(uuid),
"MAJOR :: " + String.valueOf(major),
"MINOR :: " + String.valueOf(minor)
});
// [리턴 반환 실시]
if (subscriber != null && subscriber.isDisposed() == false) {
subscriber.onNext(BEACON_ADVERTISING_STOP);
subscriber.onComplete(); // TODO [완료 처리]
}
// [비콘 신호 활성 종료]
if (beaconTransmitter != null) {
if (ActivityCompat.checkSelfPermission(mContext, Manifest.permission.BLUETOOTH_ADVERTISE) != PackageManager.PERMISSION_GRANTED) {
return;
}
beaconTransmitter.stopAdvertising();
}
return;
}
}, BEACON_ADVERTISING_TIME_OUT * 1000);
// TODO [비콘 신호 활성 수행]
beaconTransmitter = new BeaconTransmitter(mContext, beaconParser);
beaconTransmitter.startAdvertising(beacon, new AdvertiseCallback() {
@Override
public void onStartSuccess(AdvertiseSettings settingsInEffect) {
super.onStartSuccess(settingsInEffect);
// [비콘 신호 활성 성공 로그]
beacon_advertising_LOG = "[Success] : Beacon Advertising Start";
S_Log._W_(ACTIVITY_NAME + " :: observableBeaconAdvertising :: 비콘 실시간 신호 활성 수행", new String[]{
"M_LOG :: " + String.valueOf(beacon_advertising_LOG),
"UUID :: " + String.valueOf(uuid),
"MAJOR :: " + String.valueOf(major),
"MINOR :: " + String.valueOf(minor)
});
// [리턴 반환 실시]
if (subscriber != null && subscriber.isDisposed() == false) {
subscriber.onNext(BEACON_ADVERTISING_START);
//subscriber.onComplete(); // TODO [완료 처리는 비콘 신호 활성 종료 핸들러에서 처리]
}
}
@Override
public void onStartFailure(int errorCode) {
super.onStartFailure(errorCode);
// [비콘 신호 활성 실패 로그]
beacon_advertising_LOG = "[Error] : Beacon Advertising onStartFailure (ErrorCode = " +String.valueOf(errorCode)+ ")";
S_Log._E_(ACTIVITY_NAME + " :: observableBeaconAdvertising :: 비콘 실시간 신호 활성 실패", new String[]{
"M_LOG :: " + String.valueOf(beacon_advertising_LOG),
"UUID :: " + String.valueOf(uuid),
"MAJOR :: " + String.valueOf(major),
"MINOR :: " + String.valueOf(minor)
});
// [리턴 반환 실시]
if (subscriber != null && subscriber.isDisposed() == false) {
subscriber.onError(new Throwable(beacon_advertising_LOG));
subscriber.onComplete();
}
return;
}
});
}
else {
// TODO [블루투스가 Advertising 지원 하지 않은 경우 종료]
beacon_advertising_LOG = "[ERROR] : Bluetooth Advertising Support False (블루투스 신호 광고 활성 지원 확인 필요)";
S_Log._E_(ACTIVITY_NAME + " :: observableBeaconAdvertising :: 에러 발생", new String[]{String.valueOf(beacon_advertising_LOG)});
// [리턴 반환 실시]
if (subscriber != null && subscriber.isDisposed() == false) {
subscriber.onError(new Throwable(beacon_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 + " :: observableBeaconAdvertising :: EXCEPTION", new String[]{ String.valueOf(e.getMessage()) });
try {
// [에러 메시지 삽입]
beacon_advertising_LOG = "[EXCEPTION] : " + String.valueOf(e.getMessage());
// [리턴 반환 실시]
if (subscriber != null && subscriber.isDisposed() == false){
subscriber.onError(new Throwable(beacon_advertising_LOG));
subscriber.onComplete();
}
return;
}
catch (Exception ex){
ex.printStackTrace();
}
}
});
}
// --------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------
[결과 출력]
// --------------------------------------------------------------------------------------
D///===========//: ================================================
I/: [LOG :: CLASS PLACE :: com.example.javaproject.C_Module.C_Beacon_Client_Module.lambda$observableBeaconAdvertising$1(C_Beacon_Client_Module.java:432)]
I/: ----------------------------------------------------
I/: [LOG :: DESCRIPTION :: C_Beacon_Client_Module :: observableBeaconAdvertising :: 비콘 실시간 신호 활성 시작]
I/: ----------------------------------------------------
I/: [LOG :: UUID :: 03c3c219-588e-f909-db0a-320ac6deeff0]
I/: ----------------------------------------------------
I/: [LOG :: MAJOR :: 1]
I/: ----------------------------------------------------
I/: [LOG :: NINOR :: 36]
D///===========//: ================================================
D/CompatibilityChangeReporter: Compat change id reported: 263076149; UID 10510; state: DISABLED
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/BeaconParser: Parsing beacon layout: m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24
D/BluetoothAdapter: getBleEnabledArray(): ON
D/BluetoothAdapter: getBleEnabledArray(): ON
I/BluetoothAdapter: BluetoothAdapter() : com.example.javaproject.staging
D/BluetoothAdapter: getBleEnabledArray(): ON
D/BluetoothLeAdvertiser: onAdvertisingSetStarted(2, 1, 0)
I/BeaconTransmitter: Advertisement start succeeded.
W///===========//: ================================================
I/: [LOG :: CLASS PLACE :: com.example.javaproject.C_Module.C_Beacon_Client_Module$2$2.onStartSuccess(C_Beacon_Client_Module.java:595)]
I/: ----------------------------------------------------
I/: [LOG :: DESCRIPTION :: C_Beacon_Client_Module :: observableBeaconAdvertising :: 비콘 실시간 신호 활성 수행]
I/: ----------------------------------------------------
I/: [LOG :: M_LOG :: [Success] : Beacon Advertising Start]
I/: ----------------------------------------------------
I/: [LOG :: UUID :: 03c3c219-588e-f909-db0a-320ac6deeff0]
I/: ----------------------------------------------------
I/: [LOG :: MAJOR :: 1]
I/: ----------------------------------------------------
I/: [LOG :: MINOR :: 36]
W///===========//: ================================================
// --------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------
[참고 사이트]
// --------------------------------------------------------------------------------------
[altbeacon 라이브러리 사용해 실시간 비콘 신호 스캔 및 비콘 신호 활성 실시]
https://blog.naver.com/kkh0977/222346562441?trackingCode=blog_bloghome_searchlist
[alt beacon 비콘 빌드 오류 - debugCompileClasspath , Bad Gateway 502]
https://blog.naver.com/kkh0977/222623395643?trackingCode=blog_bloghome_searchlist
[비콘 (beacon) 스캔이 되지 않는 경우 해결 조치]
https://blog.naver.com/kkh0977/222696189077?trackingCode=blog_bloghome_searchlist
// --------------------------------------------------------------------------------------
반응형
'Android' 카테고리의 다른 글
Comments