안드로이드에서 제공하는 BluetoothLeScanner를 사용해서 Bluetooth 주변기기를 Scan 하는 방법을 정리했다.
권한 처리하기
Bluetooth Scan을 하기에 앞서 블루투스와 위치 정보에 대한 권한을 처리해줘야 한다.
Manifiest에 아래와 같이 블루투스와 위치 정보에 대한 권한을 추가한다.
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
MainActivity에서는 권한을 체크하는 코드를 작성한다. permissionArray에 누락된 권한이 있을 경우 Scan이 정상적으로 되지 않을 수 있다.
class MainActivity : ComponentActivity() {
private val permissionArray = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
arrayOf(
Manifest.permission.BLUETOOTH_SCAN,
Manifest.permission.BLUETOOTH_CONNECT,
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION
)
} else {
arrayOf(
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION
)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// ...
if(Build.VERSION.SDK_INT >= 31){
if(permissionArray.all{ ContextCompat.checkSelfPermission(this, it) == PackageManager.PERMISSION_GRANTED}){
Toast.makeText(this, "권한 확인", Toast.LENGTH_SHORT).show()
}
else{
requestPermissionLauncher.launch(permissionArray)
}
}
}
private val requestPermissionLauncher = registerForActivityResult(
ActivityResultContracts.RequestMultiplePermissions()
) { permissions ->
permissions.entries.forEach {
Log.d("DEBUG", "${it.key} = ${it.value}")
}
}
}
주변기기 Scan 하기
안드로이드에서 Bluetooth를 다루기 위해서는 BluetoothManager가 필요하다. BluetoothManager는 안드로이드 시스템 서비스 중 하나로 Bluetooth와의 상호 작용을 관리하는 클래스이다.
BluetoothManager로부터 BluetoothAdapter 인스턴스를 얻을 수 있는데, 이것으로 주변기기를 Scan 하거나 앱과 기기가 상호작용을 하게 한다. BluetoothAdapter의 BluetoothLeScanner를 사용해서 Ble Scan을 해보자.
val context = LocalContext.current
val bluetoothManager = context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
val bluetoothAdapter = bluetoothManager.adapter
val bluetoothLeScanner = bluetoothAdapter.bluetoothLeScanner
val scanSettings = ScanSettings.Builder()
.setScanMode(ScanSettings.SCAN_MODE_LOW_POWER)
.build()
bluetoothLeScanner.startScan(null, scanSettings, scanCallback)
BluetoothLeScanner의 '~Scan' 메서드를 사용할 때 ScanCallback을 전달하여 Scan 결과 이벤트를 처리해야 한다.
val scanCallback: ScanCallback = object : ScanCallback() {
override fun onScanResult(callbackType: Int, result: ScanResult) {
Log.d("onScanResult", result.toString())
if(result.device.name != null) {
var uuid = "null"
if(result.scanRecord?.serviceUuids != null) {
uuid = result.scanRecord!!.serviceUuids.toString()
}
val scanItem = DeviceData(
result.device.name?: "null",
uuid,
result.device.address?: "null"
)
if(!scanList.contains(scanItem)) {
scanList.add(scanItem)
}
}
}
override fun onScanFailed(errorCode: Int) {
println("onScanFailed $errorCode")
}
}
Scan을 멈추고 싶다면 BluetoothLeScanner의 stopScan 메서드에 startScan의 ScanCallback을 전달하면 된다.
bluetoothLeScanner.stopScan(scanCallback)
ScanFilter 사용하기
BluetoothLeScanner의 startScan 메서드를 보면 ScanFilter 값이 있다. ScanFilter는 특정 기준을 가진 기기만 Scan을 할 수 있게 한다. 기기의 Name이나 Address 등을 필터링할 수 있다.
ScanFilter scanFilter = new ScanFilter.Builder()
.setDeviceName("DeviceName")
.setDeviceAddress("DeviceAddress")
.setServiceUuid(ParcelUuid(serviceUuid))
.setManufacturerData(manufacturerId, manufacturerData, manufacturerDataMask)
.setServiceData(serviceUuid, serviceData)
.build();
![[Android][Compose] Bluetooth Scan 하기 - undefined - 주변기기 Scan 하기 - ScanFilter 사용하기 [Android][Compose] Bluetooth Scan 하기 - undefined - 주변기기 Scan 하기 - ScanFilter 사용하기](https://blog.kakaocdn.net/dn/uBKyK/btskXOzdcSe/LfYCDXdbRj9QRqfSo1cSyk/img.gif)
Android_Study/Ble Sample at master · OhGyong/Android_Study
안드로이드 개발 공부. Contribute to OhGyong/Android_Study development by creating an account on GitHub....
github.com
'Android > Bluetooth' 카테고리의 다른 글
[Android][Compose] Bluetooth Connect 하기 (0) | 2023.07.10 |
---|
댓글