안드로이드 개발을 처음 접한 2017년에는 안드로이드 에뮬레이터
의 성능이 좋지 않았다. 그 당시에 에뮬레이터의 성능이 좋지 않으니, 테스트는 실기기를 연결하여 진행했다. (실기기도 성능이 좋진 않았지만, 에뮬레이터보다는 확실히 빨랐다) 테스트하는 동안 유선으로 연결하고 있는 것이 불편하여 이후에는 무선으로 연결하는 방법을 찾아서 사용했었다. 이 방법도 연결할 때 1회는 유선으로 연결해야 했다.
한동안 안드로이드 개발을 하지 않다가 최근에 안드로이드 개발을 다시 시작하면서 에뮬레이터를 사용해 보니 성능이 괜찮았다. 이 정도면 실기기를 사용하지 않고 에뮬레이터를 사용해도 괜찮을 것 같았다. 다만, 한 가지 문제가 있었는데 앱이 블루투스 기능을 사용하고 있다는 점이었다.
안드로이드 에뮬레이터는 아래와 같이 블루투스 기능을 지원하지 않는다.
https://developer.android.com/studio/run/advanced-emulator-usage
호스트의 블루투스를 사용할 수 있는 방법
PC의 블루투스를 VM이나 에뮬레이터에서 사용할 수 있는 방법을 찾아보니 아래와 같이 2가지 방법이 있었다.
- google/bumble,
Android Emulator
를 사용한 방법 - VirtualBox, Android x86 를 사용한 방법
1, 2번 방법 모두 USB 블루투스 동글
이 필요하고 환경에 따라 안될 가능성이 높아 보인다. 2번 방법은 VirtualBox
가 아니더라도 호스트의 USB를 사용할 수 있는 VM이면 가능할 것으로 보인다.
아래와 같은 이유로 두 방법 중 1번 방법을 선택해서 진행했다.
- Android x86 이미지가 Android 9.0까지만 존재
- VirtualBox를 설치하고 싶지 않고 다른 VM을 찾아보는 것도 시간이 오래 걸릴 것 같은 점
- bumble 프로젝트는 알파버전이지만 꾸준히 개발되고 있고 구글 개발자 문서에 bumble 프로젝트를 사용한 예시가 있어 지원이 더 좋아질 가능성이 있음
사실, 이런 문제는 성공한 사람의 환경을 그대로 따라가는 것이 최선이다…
bumble
bumble
은 구글의 오픈소스로 앱, 에뮬레이션, 테스트 및 실험을 위한 블루투스 스택이다. Python
으로 개발되었고 아래와 같이 여러 프로토콜과 프로파일을 지원한다.
Bluetooth Stack for Apps, Emulation, Test and Experimentation
Bumble is a full-featured Bluetooth stack written entirely in Python. It supports most of the common Bluetooth Low Energy (BLE) and Bluetooth Classic (BR/EDR) protocols and profiles, including GAP, L2CAP, ATT, GATT, SMP, SDP, RFCOMM, HFP, HID and A2DP. The stack can be used with physical radios via HCI over USB, UART, or the Linux VHCI, as well as virtual radios, including the virtual Bluetooth support of the Android emulator.
README.md
의 Using Bumble With a USB Dongle 내용을 보면 전용 USB 동글
을 사용하는 것이 가장 쉽다는 내용이 있는데, 아래 적용 방법에 소개할 usb_probe
툴을 사용하기 위해서는 블루투스 USB 동글
은 쉬운 선택 사항이 아니라 필수 사항으로 보인다.
윈도우 환경에서는 드라이버를 변경하기 때문에 별도의 USB 블루투스 동글이 없어도 적용이 가능할 것 같으나, 드라이버 변경 시 기존에 페어링 된 블루투스 장비들의 연결이 해제된다. 그냥 별도의 동글을 사용하는 것이 수월하다.
적용 방법
사전 준비 및 환경
적용하기 위한 사전 준비 및 환경은 아래와 같다.
- USB 블루투스 동글: 리얼텍 (Realtek) 칩셋을 권장
- 안드로이드 에뮬레이터: 버전 33.1.4.0 이상
Android Studio Emulator Bluetooth not working 이슈와 같이 bumble-rtk-util
로 펌웨어(firmware)를 로드해야 하는 경우가 있을 수 있다. 리얼텍 칩셋의 경우 bumble에 펌웨어를 다운로드 및 로드할 수 있는 기능이 있어서 리얼텍 칩셋을 사용한 USB 블루투스 동글을 쓸 것을 권장한다.
# -----------------------------------------------------------------------------
# Constants
# -----------------------------------------------------------------------------
LINUX_KERNEL_GIT_SOURCE = (
"https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git/plain/rtl_bt",
False,
)
REALTEK_OPENSOURCE_SOURCE = (
"https://github.com/Realtek-OpenSource/android_hardware_realtek/raw/rtk1395/bt/rtkbt/Firmware/BT",
True,
)
LINUX_FROM_SCRATCH_SOURCE = (
"https://anduin.linuxfromscratch.org/sources/linux-firmware/rtl_bt",
False,
)
설치
Getting Started를 참고하여 설치를 진행했다. 먼저, 아래 명령을 입력해 Github Repository로 부터 Bumble을 설치한다.
- Github Repository로부터 Bumble 설치
> python3 -m pip install git+https://github.com/google/bumble.git
...
Successfully built bumble
Installing collected packages: bumble
Attempting uninstall: bumble
Found existing installation: bumble 0.0.195
Uninstalling bumble-0.0.195:
Successfully uninstalled bumble-0.0.195
Successfully installed bumble-0.0.195
설치가 완료되면 bumble-console
, bumble-scan
, bumble-usb-probe
등의 명령을 사용할 수 있다. 해당 명령이 실행되지 않으면 설치 경로를 환경변수에 추가한다.
- bin 폴더의 하위 목록
> ls
bumble-bench bumble-gatt-dump bumble-pandora-server bumble-show pip3
bumble-ble-rpa-tool bumble-hci-bridge bumble-rfcomm-bridge bumble-speaker pip3.9
bumble-console bumble-l2cap-bridge bumble-rtk-fw-download bumble-unbond pyserial-miniterm
bumble-controller-info bumble-link-relay bumble-rtk-util bumble-usb-probe pyserial-ports
bumble-controller-loopback bumble-pair bumble-scan pip
다른 방법으로는 Bumble Repository를 Clone하고 apps
, tools
폴더의 Python
파일을 실행해도 된다.
플랫폼(맥, 윈도우) 별 설정
플랫폼(맥, 윈도우)에 따라 아래 내용을 참고하여 설정한다.
맥 OS(macOS)
MACOS PLATFORM문서를 참고하여 아래 명령을 실행한다.
> sudo nvram bluetoothHostControllerSwitchBehavior="never"
윈도우(Windows)
WINDOWS PLATFORM 문서를 참고하여 진행했다. Zadig tool.을 설치 및 실행한 뒤 Options > List All Devices
를 선택한다. 드롭다운에서 USB 블루투스 동글을 선택한 뒤 Reinstall Driver
버튼을 눌러 드라이버를 설치한다.
정상적으로 할당되면, 장치 관리자에서 블루투스
가 아닌 범용 직렬 버스 장치
에 우리가 연결한 USB 블루투스 동글이 있는 것을 확인할 수 있다. 추가로 드라이버 세부 정보의 드라이버 파일 목록에서 winusb.sys
를 확인할 수 있다.
블루투스 스캔 기능 확인
스캔 기능을 확인하기 위해서 먼저 bumble-usb-probe
명령으로 USB 블루투스 동글의 Bumble Transport Names
를 확인한다. 아래 내용처럼 Transport를 입력하는 곳에 usb:0
or usb:0BDA:A729
or usb:0BDA:A729/00E04C239987
를 사용할 수 있다.
> bumble-usb-probe
or
> python3 /apps/usb_probe.py
ID 0BDA:A729
Bumble Transport Names: usb:0 or usb:0BDA:A729 or usb:0BDA:A729/00E04C239987
Bus/Device: 005/004
Class: Wireless Controller
Subclass/Protocol: 1/1 [Bluetooth]
Serial: 00000C239987
Manufacturer: Realtek
Product: Bluetooth 5.3 Radio
...
bumble-console
에서 scan on
명령을 실행하면 아래 그림과 같이 블루투스 스캔이 정상적으로 작동하는 지 확인할 수 있다.
> bumble-console usb:0
or
> python3 /apps/console.py usb:0
안드로이드 에뮬레이터와 연결
안드로이드 에뮬레이터
와 연결하기 위해서는 아래 두 명령을 실행한다. 첫 번째 명령은 bumble-hci-bridge
를 사용하여 안드로이드 에뮬레이터의 가상 Bluetooth Controller
인 Netsim
과 USB 블루투스 동글을 연결한다. 두 번째 명령은 에뮬레이터를 Bumble HCI Bridge
에 연결하여 실행한다.
- bumble-hci-bridge 실행
> bumble-hci-bridge android-netsim:_:8877,mode=controller usb:0
or
> python3 /apps/hci_bridge.py android-netsim:_:8877,mode=controller usb:0
- 안드로이드 에뮬레이터 실행
> emulator -packet-streamer-endpoint localhost:8877 -avd [Emulator Name] -no-snapshot-load
참고로, 안드로이드 에뮬레이터 이름은 아래 명령으로 확인할 수 있다.
> emulator -list-avds
Pixel_3a_API_34_extension_level_7_arm64-v8a
Resizable_Experimental_API_34
결과
문제가 없다면 아래 그림와 같이 안드로이드 에뮬레이터에서 블루투스를 사용할 수 있다.
참고사항
안드로이드 에뮬레이터에서 블루투스가 계속 꺼지거나 주변 기기가 검색되지 않는 경우
Android Studio Emulator Bluetooth not working 이슈와 같이 안드로이드 에뮬레이터에서 블루투스가 계속 꺼지는 현상이 발생하거나 아래 그림과 같이 bumble-console
에서 주변 기기가 검색되지 않는 경우가 있다.
- 주변 기기가 검색되지 않는 경우
이런 경우 위 이슈의 답변처럼 bumble-rtk-fw-download
, bumble-rtk-util
를 사용하여 펌웨어를 다운로드 및 로드하여 해결할 수 있다. 리얼텍 칩셋을 사용한 블루투스 동글을 사용 중이나 아래와 같이 지원하지 않는 USB 장치라고 나온다면 명시적으로 driver=rtk
을 입력하여 진행하면 된다.
- USB 블루투스 동글의 펌웨어 정보 확인
> bumble-rtk-util info usb:0
or
> python3 /tools/rtk_util.py info usb:0
USB device not supported by this RTK driver
- 지원하지 않는 USB 장치라고 나오는 경우 명시적으로
driver=rtk
를 입력하여 진행
> bumble-rtk-util info "usb:[driver=rtk]0"
or
> python3 /tools/rtk_util.py info "usb:[driver=rtk]0"
Driver:
ROM: 8761
Firmware: rtl8761bu_fw.bin
Config: rtl8761bu_config.bin
- USB 블루투스 동글에 펌웨어 로드
> bumble-rtk-util load usb:"[driver=rtk]0"
or
> python3 /tools/rtk_util.py load "usb:[driver=rtk]0"
WARNING:bumble.drivers.rtk:Firmware file rtl8761bu_fw.bin not found
WARNING:bumble.drivers.rtk:See https://google.github.io/bumble/drivers/realtek.html
Firmware already loaded or no supported driver for this device.
- 펌웨어가 없는 경우
bumble-rtk-fw-download
를 사용하여 펌웨어 다운로드
> bumble-rtk-fw-download --single rtl8761bu
or
> python3 /tools/rtk-fw-download --single rtl8761bu
Downloading
FROM: https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git/plain/rtl_bt
TO: ...
---
Downloaded rtl8761bu_fw.bin: 44484 bytes
Downloaded rtl8761bu_config.bin: 6 bytes
- USB 블루투스 동글에 펌웨어를 다시 로드
> bumble-rtk-util load usb:"[driver=rtk]0"
or
> python3 /tools/rtk_util.py load "usb:[driver=rtk]0"
이슈의 답변을 보면 자동으로 펌웨어를 로드한다고 하나, 내 환경에서는 USB 블루투스 동글을 제거하거나 PC를 재부팅 할 경우 위 명령을 다시 입력해서 펌웨어를 다시 로드해야 에뮬레이터 내부에서 블루투스를 사용할 수 있었다.
안드로이드 에뮬레이터 버전이 낮은 경우
안드로이드 에뮬레이터 버전이 33.1.4.0
이하인 경우 --packet-streamer-endpoint
옵션이 존재하지 않는다. Android Studio
의 SDK Manager
메뉴에서 Android Emulator
를 업데이트 후 진행하면 된다.
> emulator -packet-streamer-endpoint localhost:8877 -avd Resizable_Experimental_API_34 -no-snapshot-load
INFO | Android emulator version 32.1.14.0 (build_id 10330179) (CL:N/A)
...
INFO | Duplicate loglines will be removed, if you wish to see each indiviudal line launch with the -log-nofilter flag.
unknown option: -packet-streamer-endpoint
please use -help for a list of valid options
후기
안드로이드 에뮬레이터
에서 블루투스를 사용할 수 있게 되니 개발 중에 실기기를 사용하여 테스트할 이유가 없어졌다. 변경 사항 반영도 에뮬레이터를 사용하는 경우가 더 빨라서 테스트 및 기능 확인도 수월하고 훨씬 편하게 개발할 수 있게 됐다. 에뮬레이터에서 블루투스를 사용하는 것이 목적이라 이번에는 필요한 부분만 확인했지만, 블루투스를 깊게 사용하는 경우라면 이 글에서 사용한 Bumble
프로젝트를 살펴볼 만 할 것 같다.