Computer >> 컴퓨터 >  >> 시스템 >> Android

Android Bluetooth 신뢰성 향상:일관된 연결을 위한 입증된 팁

Android Bluetooth 신뢰성 향상:일관된 연결을 위한 입증된 팁

이전에 이런 일이 있었을 수도 있습니다. 무선 이어버드가 어느 날 완벽하게 연결되었다가 다음 날에는 휴대폰을 만난 적이 없는 것처럼 작동합니다. 또는 달리는 도중에 스마트워치가 떨어져 나가는 경우도 있습니다. 블루투스는 작동할 때는 놀랍지만 작동하지 않을 때는 짜증납니다.

저는 스마트 안경과 같은 웨어러블 장치의 Bluetooth 소프트웨어 엔지니어로 일하고 있으며 이러한 장치가 고장나는 이유를 추적하는 데에 인정하고 싶지 않은 것보다 더 많은 시간을 보냈습니다.

이 기사에서는 Android의 Bluetooth 스택이 실제로 어떻게 작동하는지, 왜 때때로 예측할 수 없는 것처럼 느껴지는지, 앱이나 시스템을 더욱 안정적으로 만들기 위해 개발자로서 무엇을 할 수 있는지에 대해 자세히 설명하겠습니다.

일반 영어로 된 블루투스

기본적으로 Bluetooth는 두 장치 간의 대화일 뿐입니다. 하지만 이는 단순한 하나의 커뮤니케이션 라인이 아니라 여러 레이어가 서로 겹겹이 쌓여 있는 것입니다.

  • 라디오(컨트롤러): 무선 매체를 통해 실제 신호를 보내고 받습니다.

  • 소프트웨어 브레인(호스트 스택): 누구와 어떻게 대화할지, 원하는지 결정하세요.

  • 프로필: 음악 스트리밍, 건강 데이터 동기화 등 대화의 목적을 정의하세요.

  • 프로토콜: 다른 장치와 대화하는 방법을 정의하세요.

블루투스에는 두 가지 큰 "맛"이 있습니다:

  • 기본(BR/EDR): 헤드폰이나 자동차 키트 같은 것에 사용됩니다. 더 많은 무게를 들 수 있습니다.

  • 저에너지(LE): 피트니스 밴드, 비콘 및 대부분의 웨어러블 기기에 사용됩니다. 더 오래 지속될 수 있습니다.

대부분의 최신 장치는 두 가지를 동시에 사용합니다. 이는 강력하지만 더 많은 일이 잘못될 가능성도 열어줍니다.

안드로이드가 독특한 특징을 추가하는 이유

Android Bluetooth 신뢰성 향상:일관된 연결을 위한 입증된 팁

Android에서 Bluetooth는 단지 하나의 깔끔한 패키지가 아닙니다. 움직이는 부품의 체인입니다:

  • 앱에서 BluetoothAdapter를 호출합니다. .

  • 시스템 서비스로 이동합니다. 예를 들어 AdapterService .

  • 그런 다음 JNI를 통해 네이티브 코드로 (자바 네이티브 인터페이스).

  • 그런 다음 칩 공급업체의 Bluetooth 스택으로 .

  • 마지막으로 라디오 하드웨어에 도달합니다. .

휴대폰 제조업체마다 약간씩 다른 Bluetooth 칩과 펌웨어를 제공합니다. 즉, 동일한 블루투스 앱이 삼성, Pixel 또는 Android를 실행하는 기타 저가형 휴대폰에서는 다르게 작동할 수 있다는 의미입니다.

'It Just Disconnected'의 실제 문제

제가 흔히 겪는 몇 가지 문제를 간단히 설명하면 다음과 같습니다.

결합 문제('키 분실' 문제)

두 개의 Bluetooth 장치가 페어링되면 암호화 키(클래식의 경우 링크 키, LE의 경우 장기 키)를 교환하고 이를 비휘발성 메모리에 저장합니다. 이러한 키를 사용하면 기기가 나중에 서로를 인식하고 사용자에게 다시 묻지 않고도 안전하게 다시 연결할 수 있습니다.

"일치하지 않는 메모리" 문제는 한 장치에 저장된 키가 다른 장치의 키와 더 이상 일치하지 않을 때 발생합니다. 원인은 다음과 같습니다:

  • 키를 지우거나 재생성하는 펌웨어 업데이트 또는 OS 업그레이드.

  • 한쪽은 공장 초기화 또는 '기기 삭제' 기능을 수행하지만 다른 쪽은 그렇지 않습니다.

  • 저장 공간을 확보하기 위해 시스템에서 키가 손상되거나 제거되었습니다.

사용자의 관점에서 보면 기기가 여전히 보일 수 있습니다. 페어링되었지만(Bluetooth 메뉴에 표시됨) "인증 실패" 또는 "암호화 부족"과 같은 오류로 인해 연결이 알 수 없이 실패합니다. 유일한 치료법은 일반적으로 양쪽 끝에서 기기를 삭제하고 다시 페어링하는 것인데, 이는 기술적인 지식이 없는 사용자에게는 터무니없는 일로 느껴집니다.

타이밍 불일치

Bluetooth 장치는 원할 때마다 채팅하는 것이 아니라 연결 간격에 동의합니다. 이는 본질적으로 각 측면이 "깨어나고" 패킷을 교환하는 시간에 대한 일정입니다. 두 사람이 30분에 한 번씩 카페에서 만나기로 합의했다고 생각해보세요.

불일치는 다음과 같은 경우에 발생합니다:

  • 양측은 서로 다른 간격을 협상하지만 완전히 동의하지는 않습니다(예:한쪽은 30ms라고 생각하고 다른 쪽은 50ms라고 생각함).

  • 한쪽의 펌웨어 업데이트 또는 구성 변경으로 인해 타이밍 정책이 변경됩니다.

  • 라디오 상태로 인해 한 쪽에서 여러 차례 예정된 체크인을 놓치게 되어 시계가 어긋나게 됩니다.

  • 절전 로직(휴대폰이 잠자기 모드로 전환되는 것과 같은)이 자동으로 간격을 늘립니다.

이는 연결이 처음에는 잘 작동하지만 나중에는 실패하기 시작하는 이유를 설명합니다. 장치가 처음에는 일정한 간격으로 동기화되었지만 한쪽의 정책이나 동작이 바뀌었습니다. 사용자의 관점에서 보면 오디오 끊김 현상, 입력 지연(게임 컨트롤러의 경우) 또는 "이전에는 잘 작동"한 후 무작위로 연결이 끊어지는 것처럼 보입니다.

예기치 않은 연결 끊김

Bluetooth 링크가 끝나면 무선 계층(컨트롤러)과 상위 수준 OS 스택(호스트)이 명확한 신호를 교환해야 합니다. 컨트롤러는 HCI 연결 끊김 완료 이벤트(기본적으로:“안녕, 끝났습니다”)를 보냅니다. ). 그런 다음 호스트는 내부 상태를 업데이트하고 GATT/ACL 세션을 정리한 후 다시 연결할 준비를 해야 합니다.

하지만 실제로는 항상 일치하지는 않습니다.

  • 때때로 컨트롤러는 깔끔하게 작별 인사를 하지만 호스트 스택은 상태를 제대로 업데이트하지 않습니다. 앱은 여전히 연결이 활성 상태라고 "생각"하므로 재연결 시도는 자동으로 실패합니다.

  • 일부 플랫폼은 연결 상태를 적극적으로 캐시합니다(특히 iOS). OS에서 연결이 여전히 유효하다고 판단하면 Bluetooth를 전환하거나 재부팅할 때까지 새로운 연결 시도가 시작되지 않습니다.

  • 다른 작업(예:서비스 검색, 결합 또는 암호화 설정)이 진행되는 동안 연결 끊김 이벤트가 발생하면 경쟁 조건이 발생할 수 있습니다. OS는 기기가 실제 어떤 상태인지 혼동할 수 있습니다. 안으로.

  • 일부 장치에서는 완전한 연결 해제 후 빠른 재연결 시도가 내부 쿨다운 타이머와 충돌합니다. 컨트롤러는 이를 무시하고 앱을 대기 상태로 둡니다.

사용자의 관점에서 보면 기기가 '멈춘' 것처럼 보입니다. 복구할 수 있는 유일한 방법은 기술적으로 "실패한" 것이 없더라도 Bluetooth를 전환하거나, 앱을 다시 시작하거나, 액세서리의 전원을 껐다 켜는 것입니다.

개발자가 더 나은 성과를 낼 수 있는 방법

Bluetooth 앱을 구축하는 경우 많은 어려움을 덜 수 있는 몇 가지 습관은 다음과 같습니다.

결합된 장치를 먼저 확인하세요

연결 실패의 가장 일반적인 원인 중 하나는 결합 정보 불일치입니다. 즉, 전화기와 액세서리는 더 이상 동일한 암호화 키를 공유하지 않습니다. 기기가 UI에 나타나더라도 OS에서 해당 키를 잃어버렸을 수도 있습니다.

연결을 시도하기 전에 항상 BluetoothAdapter.getBondedDevices()으로 시스템의 결합 장치 목록을 쿼리하십시오. . 예:

if (adapter.getBondedDevices().contains(targetDevice)) {
 targetDevice.connectGatt(context, false, gattCallback);
} else {
 showToast("Please re-pair this device to restore the connection.");
}

이렇게 하면 OS가 여전히 신뢰하는 장치에만 보안 연결을 시도할 수 있습니다. 대상 장치가 결합 목록에 없는 경우 혼란스러운 연결 오류를 남기는 대신 사용자에게 명확한 지침("이 장치를 다시 페어링하십시오")을 제공할 수 있습니다.

콜백을 신중하게 처리

또 다른 미묘한 함정은 STATE_CONNECTED 이벤트는 연결이 성공했음을 의미합니다. 실제로는 onConnectionStateChange() 기본 작업이 실패한 경우에도 연결된 상태를 보고할 수 있으며 실제 결과는 status에 있습니다. 논쟁. 팬텀 연결을 추적하지 않으려면 항상 status를 모두 확인하세요. 그리고 newState :

if (status == BluetoothGatt.GATT_SUCCESS &&
 newState == BluetoothProfile.STATE_CONNECTED) {
 gatt.discoverServices();
} else {
 gatt.close();
}

이 패턴은 연결이 끊어진 상태에서 서비스 검색을 시도하는 것을 방지하고 오래된 세션이 즉시 닫히도록 보장하여 스택을 완전히 재시도할 수 있도록 준비시킵니다.

실패 예상

Bluetooth 연결은 현실 세계에서 항상 실패합니다. 장치가 범위를 벗어나거나 2.4GHz 대역에서 간섭이 급증하거나 무선이 단순히 통화 중입니다. 앱이 할 수 있는 최악의 일은 긴밀한 루프에서 즉시 재시도하는 것이며, 이로 인해 배터리가 소모되고 스택이 불안정해집니다.

더 나은 접근 방식은 다음과 같이 지수 백오프를 구현하는 것입니다.

long delay = (long) Math.min(250 * Math.pow(2, attempt), 30000);
new Handler(Looper.getMainLooper()).postDelayed(connectAction, delay);

즉, 첫 번째 재시도는 빠르게(~250ms) 발생하지만 후속 재시도는 느려지고(500ms, 1초, 2초...) 합리적인 최대값으로 제한됩니다. 백오프를 사용하면 라디오나 OS에 부담을 주지 않으면서 앱의 탄력성을 높일 수 있습니다.

올바른 도구 사용

내부적으로 무슨 일이 일어나고 있는지에 대한 가시성이 없으면 연결 문제가 무작위로 보입니다. nRF Connect와 같은 도구 Android의 Bluetooth HCI 스누프 로그는 교환되는 실제 패킷을 표시하는 동시에 기기에 대해 GATT 작업을 대화형으로 검색, 연결 및 실행할 수 있습니다. 예:

Settings.Secure.putInt(context.getContentResolver(), "bluetooth_hci_log", 1);

활성화되면 logcat 추적을 캡처하고 키 누락으로 인해 실패가 발생했는지 확인할 수 있습니다(Insufficient Authentication ), 타이밍 불일치 또는 간섭. 이러한 도구를 사용하면 앱을 디버깅하는 데 도움이 될 뿐만 아니라 문제가 코드, OS 또는 액세서리 펌웨어에 있는지 여부도 확인할 수 있습니다.

Android Bluetooth 신뢰성 향상:일관된 연결을 위한 입증된 팁

더 큰 교훈

Bluetooth를 사용하면서 일반적인 엔지니어링에 적용되는 교훈을 얻었습니다.

  • 무선은 결코 완벽하지 않으므로 항상 복구를 염두에 두고 구축하세요.

  • 로그와 지표는 선택 사항이 아닙니다. 그것은 혼란을 헤쳐나가는 지도입니다.

  • 가장 간단한 솔루션은 일반적으로 지저분한 현실 세계에서 가장 잘 살아남습니다.

결론

Bluetooth는 하드웨어, 펌웨어, 소프트웨어가 모두 협력하려고 하는 체인이기 때문에 지저분합니다. Android에서는 칩과 공급업체가 다양해 더욱 까다롭습니다.

하지만 그렇다고 해서 당신이 무력하다는 뜻은 아닙니다. 레이어의 작동 방식을 이해하고 재시도, 확인 및 적절한 로깅을 통해 앱을 설계하면 사용자가 Bluetooth를 훨씬 덜 "이상한" 느낌으로 느낄 수 있습니다.

다음에 이어버드가 오작동하면 당신이 아니라는 사실을 알게 될 것입니다. 블루투스는 블루투스일 뿐이죠.

이것은 제가 블루투스 개발에 관해 쓰려고 하는 여러 기사 중 첫 번째입니다. 다음에는 Android에서 안전한 BLE(Bluetooth Low Energy) GATT 클라이언트 및 서버를 구축하는 방법에 대해 자세히 알아보겠습니다. 계속 지켜봐 주시기 바랍니다!

무료로 코딩을 배우세요. freeCodeCamp의 오픈 소스 커리큘럼은 40,000명 이상의 사람들이 개발자로 취업하는 데 도움을 주었습니다. 시작하세요