Notice
Recent Posts
Recent Comments
Link
투케이2K
413. (android/java) [android 12 / target 31] [간단 소스] beacon 비콘 신호 활성 및 비콘 스캔 - 타겟 31 대응 본문
Android
413. (android/java) [android 12 / target 31] [간단 소스] beacon 비콘 신호 활성 및 비콘 스캔 - 타겟 31 대응
투케이2K 2022. 11. 24. 16:16[개발 환경 설정]
개발 툴 : AndroidStudio
[AndroidManifest.xml : 소스 코드]
<!-- 블루투스 및 GPS : 퍼미션 설정 선언 -->
<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"/>
<!--블루투스 권한 추가 sdk 31 대응-->
<uses-permission android:name="android.permission.BLUETOOTH_SCAN"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE"/>
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
[build.gradle : 소스 코드]
// -----------------------------------------------------------
// [altbeacon : 비콘 스캔 및 신호 활성 라이브러리]
implementation 'org.altbeacon:android-beacon-library:2.+' // [최신 버전 사용]
//implementation 'org.altbeacon:android-beacon-library:2.9.2'
//implementation 'org.altbeacon:android-beacon-library:2.16.3', ext: 'aar'
//noinspection GradleCompatible
implementation 'com.android.support:localbroadcastmanager:28.0.0'
// -----------------------------------------------------------
[java : 소스 코드]
[1]. 클래스 import 및 implements 설정
import org.altbeacon.beacon.Beacon;
import org.altbeacon.beacon.BeaconConsumer;
import org.altbeacon.beacon.BeaconManager;
import org.altbeacon.beacon.BeaconParser;
import org.altbeacon.beacon.BeaconTransmitter;
import org.altbeacon.beacon.RangeNotifier;
import org.altbeacon.beacon.Region;
public class A_Main extends AppCompatActivity implements BeaconConsumer { }
[2]. 전역 변수 설정
// TODO [비콘 스캔 관련 전역 변수]
private BeaconManager beaconManager; // [비콘 매니저 객체]
private List<Beacon> beaconList = new ArrayList<>(); // [실시간 비콘 감지 배열]
int beaconScanCount = 1; // [비콘 스캔 횟수를 카운트하기 위함]
ArrayList beaconFormatList = new ArrayList<>(); // [스캔한 비콘 리스트를 포맷해서 저장하기 위함]
// TODO [비콘 신호 활성 관련 전역 변수]
Beacon beacon; // [비콘 객체]
BeaconParser beaconParser; // [비콘 파서 객체]
BeaconTransmitter beaconTransmitter; // [BeaconTransmitter]
String sendUuid = ""; // [UUID : 비콘 신호 활성 시 사용하는 값]
String sendMajor = ""; // [MAJOR : 비콘 신호 활성 시 사용하는 값]
String sendMinor = ""; // [MINOR : 비콘 신호 활성 시 사용하는 값]
[3]. 비콘 정보 셋팅
//TODO [비콘 스캐닝을 위한 초기 설정]
public void beaconSettiong(){
Log.i("---","---");
Log.d("//===========//","================================================");
Log.i("","\n"+"["+String.valueOf(ACTIVITY_NAME)+" >> beaconSettiong() :: 비콘 매니저 초기 설정 수행]");
Log.i("","\n"+"[레이아웃 :: m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24,d:25-25]");
Log.d("//===========//","================================================");
Log.i("---","---");
try {
// [비콘 매니저 생성]
beaconManager = BeaconManager.getInstanceForApplication(A_Main.this);
// [블루투스가 스캔을 중지하지 않도록 설정]
beaconManager.setEnableScheduledScanJobs(false); // TODO 이코드를 설정해야 지맘대로 블루투스가 스캔을 중지하지 않는다.
//beaconManager.setRegionStatePeristenceEnabled(false);
// [레이아웃 지정 - IOS , Android 모두 스캔 가능]
beaconManager.getBeaconParsers().add(new BeaconParser().setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24,d:25-25"));
}
catch (Exception e){
e.printStackTrace();
}
}
[4]. 비콘 신호 활성 및 종료
// TODO [SEARCH FAST] : [비콘 신호 활성]
public void startBeaconSend(final String UUID, final String MAJOR, final String MINOR){
Log.i("---","---");
Log.d("//===========//","================================================");
Log.i("","\n"+"["+String.valueOf(ACTIVITY_NAME)+" >> startBeaconSend() :: 비콘 신호 활성 수행 실시]");
Log.i("","\n"+"[UUID :: "+String.valueOf(UUID)+"]");
Log.i("","\n"+"[MAJOR :: "+String.valueOf(MAJOR)+"]");
Log.i("","\n"+"[MINOR :: "+String.valueOf(MINOR)+"]");
Log.d("//===========//","================================================");
Log.i("---","---");
// ------------------------------------------
// [이미 비콘 신호 활성이 진행 중인 경우 먼저 종료 위함]
try {
if (beaconTransmitter != null) {
stopBeaconSend();
}
}
catch (Exception e) {
//e.printStackTrace();
}
// ------------------------------------------
// [비콘 신호 활성 수행 실시]
try {
// [beacon 객체 설정 실시]
beacon = new Beacon.Builder()
.setId1(UUID.toLowerCase()) // [UUID 지정 : 소문자]
//.setId1(UUID.toUpperCase()) // [UUID 지정 : 대문자]
.setId2(MAJOR) // [major 지정]
.setId3(MINOR) // [minor 지정]
.setManufacturer(0x004c) // [제조사 지정 : IOS 호환]
//.setManufacturer(0x0118) // [제조사 지정]
.setTxPower(-59) // [신호 세기]
//.setTxPower(59) //[신호 세기]
.setDataFields(Arrays.asList(new Long[]{0L})) // [레이아웃 필드]
.build();
// [레이아웃 지정 : IOS 호환 (ibeacon)]
beaconParser = new BeaconParser().setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24");
//beaconParser = new BeaconParser().setBeaconLayout("m:2-3=beac,i:4-19,i:20-21,i:22-23,p:24-24,d:25-25");
// [비콘 신호 활성 상태 확인 실시]
beaconTransmitter = new BeaconTransmitter(getApplicationContext(), beaconParser);
beaconTransmitter.startAdvertising(beacon, new AdvertiseCallback() {
@Override
public void onStartSuccess(AdvertiseSettings settingsInEffect) {
super.onStartSuccess(settingsInEffect);
Log.i("---","---");
Log.w("//===========//","================================================");
Log.i("","\n"+"["+String.valueOf(ACTIVITY_NAME)+" >> startBeaconSend() :: 비콘 신호 활성 [성공]]");
Log.i("","\n"+"[UUID :: "+String.valueOf(UUID.toLowerCase())+"]");
Log.i("","\n"+"[MAJOR :: "+String.valueOf(MAJOR)+"]");
Log.i("","\n"+"[MINOR :: "+String.valueOf(MINOR)+"]");
Log.i("","\n"+"[시작 시간 :: "+String.valueOf(C_Util.getNowDateTime24())+"]");
Log.w("//===========//","================================================");
Log.i("---","---");
// [팝업창 호출 실시]
activityShowAlert(
0, // [블루투스 신호 활성 종료]
"[비콘 신호 활성]",
"[정상] 비콘 신호를 활성했습니다." + "\n" + "\n"
+ "UUID : " + String.valueOf(UUID.toLowerCase()) + "\n" + "\n"
+ "MAJOR : " + String.valueOf(MAJOR) + "\n" + "\n"
+ "MINOR : " + String.valueOf(MINOR) + "\n",
"종료",
"",
"");
}
@Override
public void onStartFailure(int errorCode) {
super.onStartFailure(errorCode);
Log.i("---","---");
Log.e("//===========//","================================================");
Log.i("","\n"+"["+String.valueOf(ACTIVITY_NAME)+" >> startBeaconSend() :: 비콘 신호 활성 [실패]]");
Log.i("","\n"+"[UUID :: "+String.valueOf(UUID)+"]");
Log.i("","\n"+"[MAJOR :: "+String.valueOf(MAJOR)+"]");
Log.i("","\n"+"[MINOR :: "+String.valueOf(MINOR)+"]");
Log.i("","\n"+"[Error :: "+String.valueOf(errorCode)+"]");
Log.e("//===========//","================================================");
Log.i("---","---");
// [팝업창 호출 실시]
activityShowAlert(
0, // [블루투스 신호 활성 종료]
"[비콘 신호 활성]",
"[에러] 비콘 신호 활성에 문제가 발생했습니다." + "\n" + "\n"
+ "errorCode : " + String.valueOf(errorCode) + "\n",
"확인",
"",
"");
}
});
}
catch (Exception e){
e.printStackTrace();
}
// ------------------------------------------
}
// TODO [SEARCH FAST] : [비콘 신호 활성]
public void stopBeaconSend(){
Log.i("---","---");
Log.e("//===========//","================================================");
Log.i("","\n"+"["+String.valueOf(ACTIVITY_NAME)+" >> stopBeaconSend() :: 비콘 신호 활성 종료 실시]");
Log.e("//===========//","================================================");
Log.i("---","---");
try {
// [변수 값 초기화 지정 실시]
beacon = null;
if (beaconTransmitter != null) {
beaconTransmitter.stopAdvertising();
}
}
catch (Exception e){
e.printStackTrace();
}
}
[5]. 비콘 신호 스캔 및 종료
// TODO [SEARCH FAST] : [비콘 스캔 수행]
public void startBeaconScan(){
Log.i("---","---");
Log.w("//===========//","================================================");
Log.i("","\n"+"["+String.valueOf(ACTIVITY_NAME)+" >> startBeaconScan() :: 실시간 비콘 스캔 [시작] 실시]");
Log.w("//===========//","================================================");
Log.i("---","---");
try {
// [이미 비콘이 진행 중인 경우 종료 실시]
stopBeaconScan();
// [비콘 스캔 카운트 변수값 초기화 실시]
beaconScanCount = 1;
// [비콘 배열 데이터 초기화 실시]
if (beaconList != null && beaconList.size()>0){
beaconList.clear();
}
if (beaconFormatList != null && beaconFormatList.size()>0){
beaconFormatList.clear();
}
// [beaconManager Bind 설정]
beaconManager.bind(A_Main.this);
// [실시간 비콘 스캔 수행 핸들러 호출]
beaconScanHandler.sendEmptyMessage(0);
}
catch (Exception e){
e.printStackTrace();
}
}
// TODO [SEARCH FAST] : [비콘 스캔 수행]
public void stopBeaconScan(){
Log.i("---","---");
Log.e("//===========//","================================================");
Log.i("","\n"+"["+String.valueOf(ACTIVITY_NAME)+" >> stopBeaconScan() :: 실시간 비콘 스캔 [종료] 실시]");
Log.e("//===========//","================================================");
Log.i("---","---");
try {
// -----------------------------------------
// [비콘 스캔 카운트 초기화]
beaconScanCount = 1;
// -----------------------------------------
// [비콘 배열 데이터 초기화 실시]
if (beaconList != null && beaconList.size()>0){
beaconList.clear();
}
if (beaconFormatList != null && beaconFormatList.size()>0){
beaconFormatList.clear();
}
// -----------------------------------------
// [핸들러 사용 종료]
try {
if (beaconScanHandler != null){
beaconScanHandler.removeMessages(0);
beaconScanHandler.removeCallbacks(null);
}
}
catch (Exception e){
e.printStackTrace();
}
// -----------------------------------------
// [beaconManager Bind 해제]
try {
if(beaconManager != null){
beaconManager.unbind(A_Main.this);
}
}
catch (Exception e){
e.printStackTrace();
}
// -----------------------------------------
}
catch (Exception e){
e.printStackTrace();
}
}
// TODO [SEARCH FAST] : [비콘 스캔 수행] : [실시간 비콘 스캐닝 감지 부분]
@Override
public void onBeaconServiceConnect() {
RangeNotifier rangeNotifier = new RangeNotifier() {
@Override
public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region region) {
// [비콘이 감지되면 해당 함수가 호출]
// TODO [비콘들에 대응하는 Region 객체가 들어들어옴]
if (beacons.size() > 0) {
if (beaconList != null){
beaconList.clear();
}
for (Beacon beacon : beacons) {
if (beaconList != null){
beaconList.add(beacon);
}
}
}
else {
// TODO [실시간 스캔 반영을 위해 스캔 된 것이 없어도 기존 목록 초기화 실시]
if (beaconList != null && beaconList.size() > 0){
beaconList.clear();
}
}
}
};
try {
beaconManager.startRangingBeaconsInRegion(new Region("myRangingUniqueId", null, null, null));
beaconManager.addRangeNotifier(rangeNotifier);
beaconManager.startRangingBeaconsInRegion(new Region("myRangingUniqueId", null, null, null));
beaconManager.addRangeNotifier(rangeNotifier);
}
catch (RemoteException e) {
e.printStackTrace();
}
}
Handler beaconScanHandler = new Handler() {
public void handleMessage(Message msg) {
try {
// [기존에 저장된 배열 데이터 초기화 실시]
if(beaconFormatList != null && beaconFormatList.size() > 0){
beaconFormatList.clear();
}
// [for 문 사용해 실시간 스캔된 비콘 개별 정보 확인]
if (beaconList != null){
for(Beacon beacon : beaconList){
// TODO [비콘 스캔 정보 추출 참고]
/*
Log.d("//===========//","================================================");
Log.i("","\n"+"["+String.valueOf(ACTIVITY_NAME)+" >> beaconScanHandler() :: 실시간 비콘 스캔 [개별] 정보 확인 실시]");
Log.i("","\n"+"[비콘 스캔 Name] "+" ["+String.valueOf(beacon.getBluetoothName())+"]");
Log.i("","\n"+"[비콘 스캔 MAC] "+" ["+String.valueOf(beacon.getBluetoothAddress())+"]");
Log.i("","\n"+"[비콘 스캔 UUID] "+" ["+String.valueOf(beacon.getId1().toString())+"]");
Log.i("","\n"+"[비콘 스캔 Major] "+" ["+String.valueOf(beacon.getId2().toString())+"]");
Log.i("","\n"+"[비콘 스캔 Minor] "+" ["+String.valueOf(beacon.getId3().toString())+"]");
Log.i("","\n"+"[비콘 스캔 MPower] "+" ["+String.valueOf(beacon.getTxPower())+"]");
Log.i("","\n"+"[비콘 스캔 RSSI] "+" ["+String.valueOf(beacon.getRssi())+"]");
Log.i("","\n"+"[비콘 스캔 ServiceUuid] "+" ["+String.valueOf(beacon.getServiceUuid())+"]");
Log.i("","\n"+"[비콘 스캔 beacon] "+" ["+String.valueOf(beacon.toString())+"]");
Log.d("//===========//","================================================");
// */
// [스캔한 비콘 정보 포맷 실시]
JSONObject jsonBeacon = new JSONObject();
// [UUID : 소문자 변환]
jsonBeacon.put("uuid", String.valueOf(beacon.getId1().toString().toLowerCase()));
// [minor (36)]
jsonBeacon.put("minor", String.valueOf(beacon.getId3().toString()));
// [major (1)]
jsonBeacon.put("major", String.valueOf(beacon.getId2().toString()));
// [배열에 데이터 저장 실시]
beaconFormatList.add(jsonBeacon.toString());
} // [for 문 종료]
}
// [실시간 스캔된 비콘 정보 확인 실시]
Log.i("---","---");
Log.w("//===========//","================================================");
Log.i("","\n"+"["+String.valueOf(ACTIVITY_NAME)+" >> beaconScanHandler() :: 실시간 비콘 스캔 [전체] 정보 확인 실시]");
Log.i("","\n"+"[비콘 스캔 실행 횟수] "+" ["+String.valueOf(beaconScanCount)+"]");
Log.i("","\n"+"[비콘 스캔 개수 확인] "+" ["+String.valueOf(beaconFormatList.size())+"]");
Log.i("","\n"+"[비콘 스캔 정보 확인] [스캔 포맷 값] "+" ["+String.valueOf(beaconFormatList.toString())+"]");
Log.w("//===========//","================================================");
Log.i("---","---");
// [자바스크립트로 데이터 전송 실시]
new Android_To_Javascript().scanList(beaconFormatList.toString());
// [비콘 스캔 카운트 증가]
beaconScanCount ++;
// [핸들러 자기 자신을 1초마다 호출]
beaconScanHandler.sendEmptyMessageDelayed(0, 1000);
}
catch (Exception e){
e.printStackTrace();
}
}
};
반응형
'Android' 카테고리의 다른 글
Comments