안드로이드 앱에서 외부 기기와 블루투스를 통해 통신을 하고 있다. 요구사항에 따르면 홈 버튼을 눌러서 앱을 나가더라도 블루투스 기기로부터 데이터를 받아올 수 있어야 한다. 또 다른 요구사항으로는 화면 전환을 하더라도 기존에 수행하고 있던 블루투스 통신이 끊어지면 안되고 계속 유지되어야 한다.
이를 위해 bleService 객체를 Foreground Service로 등록하여 앱 전역에서 객체를 공유하여 사용하고 앱을 나가더라도 블루투스 통신을 통해 데이터를 받아오려고 한다.
@AndroidEntryPoint
class MainActivity : ComponentActivity() {
private lateinit var bluetoothManager: BluetoothManager
private lateinit var bluetoothAdapter: BluetoothAdapter
private lateinit var scanner: BluetoothLeScanner
private var bleService: BleService? = null
private var isServiceBound = false
private val serviceConnection = object: ServiceConnection {
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
val binder = service as BleService.LocalBinder
bleService = binder.getService()
isServiceBound = true
}
override fun onServiceDisconnected(name: ComponentName?) {
isServiceBound = false
bleService = null
}
}
private val onClickBtnConnect = { macAddress: String ->
connectToDevice(macAddress = macAddress)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
startAndBindBleService()
bluetoothManager = getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
bluetoothAdapter = bluetoothManager.adapter
scanner = bluetoothAdapter.bluetoothLeScanner
setContent {
// 생략
}
}
private fun startAndBindBleService() {
val serviceIntent = Intent(this, BleService::class.java)
startService(serviceIntent)
bindService(serviceIntent, serviceConnection, Context.BIND_AUTO_CREATE)
}
private fun connectToDevice(macAddress: String) {
if (isServiceBound) {
bleService?.connect(address = macAddress, bluetoothManager = bluetoothManager)
} else {
Log.e("MainActivity", "BleService가 바인딩되지 않았습니다.")
}
}
// 생략
fun startBluetoothScan(
addOrUpdateDevice: (String, String, Int) -> Unit = { s: String, s1: String, i: Int -> }
) {
val scanCallback = object : ScanCallback() {
override fun onScanResult(callbackType: Int, result: ScanResult?) {
super.onScanResult(callbackType, result)
result?.let {
val advertisedUuids = it.scanRecord?.serviceUuids
if (advertisedUuids != null) {
for (uuid in advertisedUuids) {
if (uuid.uuid.toString() == Config.UUID) {
val rssi = result.rssi
if (it.device.name != null) addOrUpdateDevice(it.device.name, it.device.address, rssi)
}
}
}
}
}
override fun onScanFailed(errorCode: Int) {
super.onScanFailed(errorCode)
}
}
if (ActivityCompat.checkSelfPermission(
this,
Manifest.permission.BLUETOOTH_SCAN
) != PackageManager.PERMISSION_GRANTED
) {
return
}
scanner.startScan(scanCallback)
}
// 생략
override fun onDestroy() {
super.onDestroy()
if (isServiceBound) {
unbindService(serviceConnection)
isServiceBound = false
}
}
}