안드로이드 블루투스(Bluetooth)
-블루투스를 사용하여 통신하려면 기기에서 지원되는지 확인하고, 지원되는 경우 활성화 해야한다.
-블루투스가 지원되지 않는 경우 모든 블루투스 기능을 비활성화 해야한다.
-블루투스 지원O, 비활성화 된경우
애플리케이션을 떠나지 않은 상태에서 블루투스를 활성화하도록 요철할 수 있다.(BluetoothAdapter)
1.BluetoothAdapter를 가져옵니다.
val bluetoothAdapter: BluetoothAdapter? = BluetoothAdapter.getDefaultAdapter()
if (bluetoothAdapter == null) {
// Device doesn't support Bluetooth
}
2.블루투스 활성화
블루투스 활성화를 요청하려면 startActivityForResult()호출하고 ACTION_REQUEST_ENABLE 인텐트 작업에서 전달.
if (bluetoothAdapter?.isEnabled == false) {
val enableBtIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT)
}
사용자가 "Yes"를 선택하면 시스템이 블루투스를 활성화하기 시작하고 해당 프로세스가 완료(또는 실패)되면 포커스가 애플리케이션으로 돌아갑니다.
startActivityForResult()로 전달된 REQUEST_ENABLE_BT 상수는 로컬에서 정의된 정수로,
0보다 커야 합니다. 시스템은 onActivityResult() 구현에서 requestCode 매개변수로 이 상수를 다시 전달합니다.
블루투스 활성화에 성공하면 Activity가 onActivityResult() 콜백에서 RESULT_OK 결과 코드를 수신합니다.
오류 때문에 블루투스를 활성화하지 못한 경우(또는 사용자가 "No"를 선택한 경우) 결과 코드는 RESULT_CANCELED입니다.
옵션: 애플리케이션이 ACTION_STATE_CHANGED 브로드캐스트 인텐트를 수신 대기할 수도 있다.
이것은 블루투스 상태가 변경될 때마다 시스템이 브로드캐스트한다.
이 브로드 캐스트는 새로운 블루투스 상태와 이전 블루투스 상태를 각각 포함하는 엑스트라 필드
EXTRA_STATE 및 EXTRA_PREVIOUS_STATE를 포함한다.
이 엑스트라 필드에 사용 가능한 값은 STATE_TURNING_ON, STATE_ON, STATE_TURNING_OFF 및 STATE_OFF입니다.
3.블루투스 디바이스 찾기
BluetoothAdapter를 사용하면 기기 검색을 통해서 페어링된 기기목록을 쿼리하여 원격 블루투스 기기를 찾을 수 있다.
기기 검색은 주변 지역을 검색하여 블루투스 지원 기기가 있는지 찾아 각 기기에 관한 일부 정보를 요청하는 스캔절차이다.
다만 근처에 있는 블루투스 기기가 검색 요청에 응답하려면 해당 기기가 검색 가능한 상태로 현재 정보 요청을 수락하고 있어야한다.
기기가 검색 가능한 경우 기기 이름, 클래스 및 고유 MAC주소와 같은 정보를 공유하여 검색 요청에 응답합니다.
원격기기와 처음으로 연결되면 페어링 요청이 자동으로 사용자에게 제공
기기가 페어링 되면 해당 기기에 대한 정보는 저장되고 Bluetooth API를 사용하여 읽을 수 있습니다.
원격기기에 대해 알려진 MAC주소를 사용하면 검색을 수행하지 않고 언제든지 연결 할 수 있다.
-페어링된 것과 연결된 것의 차이.
-페어링은 두 기기가 서로의 존재를 알고, 인증에 사용할 수 있는 공유 링크 키를 가지고 있으며, 서로 암호화된 연결을 설정할 수 있다는 것을 의미.
-연결은 기기가 현재 RFCOMM 채널을 공유하고 있고 데이터를 서로 전송할 수 있다는 것을 의미.
현재 Android Bluetooth API는 RFCOMM연결을 설정할 수 있기 전에 기기를 페어링하도록 요청합니다.
Bluetooth API와 암호화된 연결을 시작하면 페어링이 자동으로 실행됩니다.
참고: Android기기는 기본적으로 검색할 수 없습니다.
사용자가 시스템 설정을 통해 제한된 시간 동안 기기 검색이 가능하도록 설정하거나, 사용자가 애플리케이션을 떠나지 않고
검색 기능을 활성화하도록 애플리케이션에서 요청할 수 있습니다.
4. 페어링된 기기 쿼리
기기 검색을 수행하기 전에 페어링된 기기 집합을 쿼리하여 원하는 기기가 이미 있는지 확인하는것이 좋다.
그렇게 하려면 getBondedDevices()를 호출
이렇게 하면 페어링 기기 BluetoothDevice객체 세트 반환.
val pairedDevices: Set<BluetoothDevice>? = bluetoothAdapter?.bondedDevices
pairedDevices?.forEach { device ->
val deviceName = device.name
val deviceHardwareAddress = device.address // MAC address
}
블루투스 기기와 연결을 시작하려면 MAC 주소만 있으면 된다.
주의: 기기 검색을 수행하면 블루투스 어댑터의 리소스가 많이 소모된다. 연결할 기기를 검색한 뒤에는 연결을 시도하기전에
cancelDiscovery()를 사용하여 검색을 중단했는지 확인.
또한 기기에 연결된 상태로 검색을 수행하면 안 됩니다.
검색 프로세스가 기존연결에서 사용 가능한 대역폭을 대폭 감소시키기 때문.
5. 블루투스 디바이스 검색
기기 검색을 시작하려면 startDiscovery()를 호출합니다.
이 프로세스는 비동기식 검색이고 성공적으로 시작되었는지 나타내는 부울 값을 반환.
일반적으로 검색 프로세스는 12초 정도의 조회 스캔과, 정보를 가져오는 과정이 포함.
애플리케이션이 검색된 각 기기에 대한 정보를 수신하려면 ACTION_FOUND 인텐트에 대한 BroadcastReceiver를 등록해야 한다.
인텐트에는 EXTRA_DEVICE 및 EXTRA_CLASS가 포함.
이 엑스트라 필드에는 각각 BluetoothDevice 및 BluetoothClass가 포함.
override fun onCreate(savedInstanceState: Bundle?) {
...
// Register for broadcasts when a device is discovered.
val filter = IntentFilter(BluetoothDevice.ACTION_FOUND)
registerReceiver(receiver, filter)
}
// Create a BroadcastReceiver for ACTION_FOUND.
private val receiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val action: String = intent.action
when(action) {
BluetoothDevice.ACTION_FOUND -> {
// Discovery has found a device. Get the BluetoothDevice
// object and its info from the Intent.
val device: BluetoothDevice =
intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE)
val deviceName = device.name
val deviceHardwareAddress = device.address // MAC address
}
}
}
}
override fun onDestroy() {
super.onDestroy()
...
// Don't forget to unregister the ACTION_FOUND receiver.
unregisterReceiver(receiver)
}
-검색 기능 활성화
로컬 기기를 다른기기가 검색할 수 있게 하려면 ACTION_REQUEST_DISCVERABLE인텐트를 사용하여
startActivityForResult를 호출합니다.
이렇게 하면 설정 앱으로 이동할 필요 없이 시스템의 검색 가능한 모드를 활성화하도록 요청합니다.
6. 블루투스 연결
두 기기 간 연결을 생성하려면 서버와 클라이언트 모두 구현해야 한다.
왜냐하면 한 기기는 서버 소켓을 열고 다른 기기는 서버 기기의 MAC주소를 사용하여 연결을 시작해야 하기 때문.
서버 기기와 클라이언트 기기는 각각 필요한 BluetoothSocket을 서로 다른 방식으로 획득합니다.
서버는 수신되는 연결을 수락할 때 소켓 정보를 받습니다.
클라이언트가 서버에 대한 RFCOMM채널을 열 때 소켓정보를 제공합니다.
서버와 클라이언트는 각각 동일한 RFCOMM채널에 연결된 BluetoothSocket이 있는 경우 서로 연결된 것으로 간주.
이 시점에서 각 기기가 입력 및 출력 스트림을 획득할 수 있고 데이터 전송을 시작할 수 있다.
참고: 이전에 두 기기가 페어링되지 않은 경우, Android 프레임워크가 연결 프로세스에서 사용자에게 페어링 요청알림
또는 대화상자를 자동으로 표시(페어링 할거냐는 alert)
따라서 기기 연결을 시도할 때 애플리케이션은 기기 페어링 여부에 대해 걱정할 필요가 없다.
참조 :
http://jinyongjeong.github.io/2018/09/27/bluetoothpairing/
https://github.com/Polidea/RxAndroidBle
https://github.com/Jasonchenlijian/FastBle
'안드로이드' 카테고리의 다른 글
sharedViewModel, Android Fragment간의 ViewModel공유하기 (0) | 2022.10.25 |
---|---|
[Android] Architecture, Framework, Platform에 대해 알아보자 (0) | 2022.10.24 |
[Android] 블루투스(Bluetooth) Gatt 개발 순서 (0) | 2022.10.24 |
[Android] ViewPager2, tabLayout 사용 방법 (0) | 2022.10.24 |
[Android] viewpager setUserVisibleHint, swipe, transition, 양쪽 마진 (0) | 2022.10.24 |