BluetoothAdapter — systémová třída Androidu představující místní Bluetooth adaptér zařízení. BluetoothAdapter je vstupním bodem pro všechny Bluetooth operace v Androidu: zapnutí rádia (enable), skenování zařízení, správa viditelnosti (setScanMode), získání informací o adaptéru (getName, getAddress, getState). Třída je dostupná přes BluetoothManager.getAdapter() (API 18+) nebo BluetoothAdapter.getDefaultAdapter(). Na zařízeních bez Bluetooth modulu vrací getDefaultAdapter() null. Podle Android Developers, 2026 je BluetoothAdapter povinnou součástí každé BLE aplikace v Androidu, počínaje API 5.
Hlavní body
BluetoothAdapter představuje fyzický Bluetooth adaptér zařízení s Androidem. Každé zařízení má právě jeden adaptér (výjimka — Android Automotive s několika Bluetooth čipy, kde se používá BluetoothManager.getAdapterList()). BluetoothAdapter zapouzdřuje stav rádia: STATE_OFF (0), STATE_TURNING_ON (1), STATE_ON (2), STATE_TURNING_OFF (3). Stav je sledován přes BroadcastReceiver na ACTION_STATE_CHANGED.
Získání instance BluetoothAdapter je prvním krokem každé BLE aplikace v Androidu. Doporučená metoda — přes BluetoothManager.getAdapter() od API 18+. Alternativa — statická metoda BluetoothAdapter.getDefaultAdapter(), která funguje od API 5, ale je méně flexibilní. Obě metody vracejí null, pokud zařízení nemá Bluetooth modul (tablety Wi-Fi-only, emulátor). Kontrola null je povinná: aplikace se musí správně ukončit nebo deaktivovat BLE funkce.
// Získání BluetoothAdapter (doporučeno)
import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothManager
import android.content.Context
class BluetoothHelper(context: Context) {
private val bluetoothAdapter: BluetoothAdapter?
init {
// Metoda 1: přes BluetoothManager (API 18+)
val manager = context.getSystemService(Context.BLUETOOTH_SERVICE)
as BluetoothManager?
bluetoothAdapter = manager?.adapter
// Metoda 2: přes statickou metodu (API 5+)
// val adapter = BluetoothAdapter.getDefaultAdapter()
// Kontrola null
if (bluetoothAdapter == null) {
// Zařízení nepodporuje Bluetooth
}
}
// Zkontrolovat stav Bluetooth
fun isBluetoothEnabled(): Boolean {
return bluetoothAdapter?.isEnabled == true
}
// Získat informace o adaptéru
fun getAdapterInfo(): Map<String, String> {
return mapOf(
"name" to (bluetoothAdapter?.name ?: "N/A"),
"address" to (bluetoothAdapter?.address ?: "N/A"),
"state" to (bluetoothAdapter?.state?.toString() ?: "N/A"),
"scanMode" to (bluetoothAdapter?.scanMode?.toString() ?: "N/A")
)
}
}
Třída BluetoothHelper demonstruje získání BluetoothAdapter přes BluetoothManager s následnou kontrolou null. isBluetoothEnabled kontroluje isEnabled — povinná podmínka před jakýmikoli BLE operacemi. getAdapterInfo vrací název zařízení, MAC adresu, stav a režim viditelnosti. Důležité: v Android 10+ (API 29+) systémová služba vrací fiktivní MAC adresu (02:00:00:00:00:00), pokud aplikace nemá oprávnění BLUETOOTH_ADMIN a ACCESS_FINE_LOCATION.
BluetoothAdapter poskytuje metody správy Bluetooth rádia. enable() a disable() zapínají a vypínají Bluetooth. Obě metody vyžadují oprávnění BLUETOOTH_ADMIN a provádějí se asynchronně: po zavolání enable() systém spustí proces zapnutí rádia, stav je sledován přes BroadcastReceiver s akcí BluetoothAdapter.ACTION_STATE_CHANGED. Od Androidu 10+ vyžadují enable() a disable() dodatečné systémové oprávnění — běžné aplikace nemohou programově spravovat Bluetooth bez dialogu uživatele.
getState() vrací aktuální stav adaptéru: STATE_OFF (10), STATE_TURNING_ON (11), STATE_ON (12), STATE_TURNING_OFF (13). getAddress() vrací MAC adresu Bluetooth adaptéru. V Androidu 6+ je pro vyžádání MAC adresy vyžadován ACCESS_FINE_LOCATION (nebo ACCESS_COARSE_LOCATION pro API 31+). V Androidu 10+ vrací getAddress() konstantní adresu 02:00:00:00:00:00 — skutečná adresa není přes veřejné API k dispozici.
getScanMode() určuje režim viditelnosti adaptéru: SCAN_MODE_NONE (neviditelný), SCAN_MODE_CONNECTABLE (viditelný pro připojené), SCAN_MODE_CONNECTABLE_DISCOVERABLE (viditelný pro všechny). Režim viditelnosti je časově omezen (obvykle 60–300 sekund) z bezpečnostních důvodů. Nastavení režimu přes setScanMode() vyžaduje BLUETOOTH_ADMIN a systémové oprávnění v Androidu 10+.
| Metoda | Popis | Požadované oprávnění |
|---|---|---|
| enable() | Zapnutí Bluetooth rádia | BLUETOOTH_ADMIN |
| disable() | Vypnutí Bluetooth rádia | BLUETOOTH_ADMIN |
| getState() | Aktuální stav adaptéru | BLUETOOTH |
| getAddress() | MAC adresa adaptéru | BLUETOOTH + ACCESS_FINE_LOCATION (API 23+) |
| getScanMode() | Režim viditelnosti zařízení | BLUETOOTH |
| setScanMode() | Nastavení režimu viditelnosti | BLUETOOTH_ADMIN |
BluetoothAdapter podporuje dva typy skenování. Klasické Bluetooth skenování (BR/EDR) se spouští přes startDiscovery() — detekuje Bluetooth zařízení všech typů, včetně telefonů a sluchátek. Výsledky jsou vráceny přes BroadcastReceiver s akcí BluetoothDevice.ACTION_FOUND. startDiscovery() pracuje 12 sekund a lze jej zrušit voláním cancelDiscovery(). Tato metoda je pro BLE zastaralá — používejte BluetoothLeScanner.
Skenování BLE přes BluetoothAdapter se provádí zastaralou metodou startLeScan(LeScanCallback). Od API 21 Google doporučuje používat BluetoothLeScanner, získaný přes BluetoothAdapter.getBluetoothLeScanner(). BluetoothLeScanner poskytuje flexibilnější API: konfiguraci skenování přes ScanSettings (režim, callback type, match mode), filtrování přes ScanFilter (podle UUID služby, názvu zařízení, MAC adresy) a podporu PendingIntent pro skenování na pozadí.
// Staré (zastaralé) vs nové BLE skenovací API
import android.bluetooth.BluetoothAdapter
import android.bluetooth.le.*
class BLEScanner(private val bluetoothAdapter: BluetoothAdapter?) {
// ZASTARALÉ: startLeScan (API 18+, API 21)
@Suppress("DEPRECATION")
fun legacyScan() {
bluetoothAdapter?.startLeScan { device, rssi, scanRecord ->
print("Found (LE Scan): $device.name, RSSI: $rssi")
}
}
// NOVÉ: BluetoothLeScanner (API 21+)
fun modernScan() {
val scanner = bluetoothAdapter?.bluetoothLeScanner
?: return
// Nastavení skenování
val settings = ScanSettings.Builder()
.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
.setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES)
.setMatchMode(ScanSettings.MATCH_MODE_AGGRESSIVE)
.build()
// Filtrovat podle služby (UUID pulsu)
val filters = listOf(
ScanFilter.Builder()
.setServiceUuid(ParcelUuid.fromString("0000180D-0000-1000-8000-00805F9B34FB"))
.build()
)
// Zahájit skenování
scanner.startScan(filters, settings, object : ScanCallback() {
override fun onScanResult(callbackType: Int, result: ScanResult) {
val device = result.device
val rssi = result.rssi
print("Found (BLE Scanner): ${device.name}, RSSI: $rssi, address: ${device.address}")
}
override fun onScanFailed(errorCode: Int) {
print("Scan error: $errorCode")
}
})
}
}
Třída BLEScanner porovnává zastaralý startLeScan a moderní BluetoothLeScanner. V legacyScan callback LeScanCallback přijímá BluetoothDevice, RSSI a syrový scanRecord. V modernScan se používá ScanSettings s režimem LOW_LATENCY (maximální rychlost detekce) a ScanFilter pro filtrování podle UUID služby pulsu (Heart Rate Service 0x180D). ScanCallback poskytuje onScanResult s objektem ScanResult obsahujícím rozšířené informace: název, RSSI, reklamní data, typ připojení.
BluetoothManager — systémová služba Androidu, zavedená v API 18 (Android 4.3), pro správu Bluetooth operací. Před API 18 byl jediným způsobem získání BluetoothAdapter statická metoda getDefaultAdapter(). BluetoothManager poskytuje: adapter — instanci BluetoothAdapter, getConnectedDevices() — seznam připojených zařízení, getDevicesMatchingConnectionStates() — filtrování podle stavu. BluetoothManager se také používá pro získání BluetoothLeScanner na starších API.
Výhody BluetoothManager oproti přímému volání BluetoothAdapter.getDefaultAdapter(): aplikace není závislá na statickém singletonu, manažer zohledňuje kontext (Activity/Application), což je důležité pro multiúčtové scénáře Android Enterprise. V Android Automotive s několika Bluetooth čipy vrací BluetoothManager.getAdapterList() všechny dostupné adaptéry — BluetoothAdapter.getDefaultAdapter() vrací pouze první.
// Použití BluetoothManager pro BLE
class BLEConnection(context: Context) {
private val bluetoothManager: BluetoothManager =
context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
private val adapter: BluetoothAdapter? = bluetoothManager.adapter
// Získat seznam připojených BLE zařízení
fun getConnectedDevices(): List<BluetoothDevice> {
return bluetoothManager.getConnectedDevices(
BluetoothProfile.GATT
)
}
// Filtrovat zařízení podle stavu
fun getDevicesByState(states: IntArray): List<BluetoothDevice> {
return bluetoothManager.getDevicesMatchingConnectionStates(
BluetoothProfile.GATT, states
)
}
// Zkontrolovat podporu BLE na zařízení
fun isBLESupported(): Boolean {
return adapter != null && context.packageManager
.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)
}
// Požádat o zapnutí Bluetooth přes systémový dialog
fun requestEnableBluetooth(activity: MainActivity) {
if (adapter?.isEnabled == false) {
val intent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
activity.startActivityForResult(intent, REQUEST_ENABLE_BT)
}
}
companion object {
const val REQUEST_ENABLE_BT = 1001
}
}
Třída BLEConnection používá BluetoothManager pro přístup k BluetoothAdapter a získání seznamu připojených GATT zařízení. isBLESupported kontroluje přítomnost BLE rádia přes PackageManager.hasSystemFeature(FEATURE_BLUETOOTH_LE) — důležitá kontrola pro zařízení s Bluetooth Classic bez BLE. requestEnableBluetooth zobrazuje systémový dialog pro zapnutí Bluetooth (ACTION_REQUEST_ENABLE), bez potřeby oprávnění BLUETOOTH_ADMIN — toto je jediný legální způsob zapnutí Bluetooth v Androidu 10+ bez systémové aplikace.
Oprávnění pro BluetoothAdapter se vyvíjela s každou verzí Androidu. V Androidu 6–11 (API 23–30) jsou pro BLE skenování povinné BLUETOOTH, BLUETOOTH_ADMIN a ACCESS_FINE_LOCATION. V Androidu 12+ (API 31+) Google rozdělil oprávnění: ACCESS_FINE_LOCATION byl nahrazen BLUETOOTH_SCAN (skenování), BLUETOOTH_CONNECT (připojení), BLUETOOTH_ADVERTISE (reklama). Pro hledání BLE zařízení stačí BLUETOOTH_SCAN, poloha není vyžadována.
Tabulka oprávnění podle verzí Androidu:
| Operace | API 23–30 | API 31+ |
|---|---|---|
| Skenování BLE | ACCESS_FINE_LOCATION | BLUETOOTH_SCAN (bez polohy) |
| Připojení k BLE | ACCESS_FINE_LOCATION | BLUETOOTH_CONNECT |
| Reklama BLE | ACCESS_FINE_LOCATION | BLUETOOTH_ADVERTISE |
| Zapnutí/vypnutí | BLUETOOTH_ADMIN | BLUETOOTH_ADMIN (systémové) |
| Získání MAC adresy | ACCESS_FINE_LOCATION | BLUETOOTH_CONNECT (fiktivní adresa) |
V Androidu 12+ jsou všechna Bluetooth oprávnění runtime oprávnění — musí být vyžádána za běhu přes ActivityResultContracts.RequestMultiplePermissions. BLUETOOTH_SCAN a BLUETOOTH_ADVERTISE patří do skupiny NEARBY_DEVICES, BLUETOOTH_CONNECT — do stejné skupiny. Oprávnění BLUETOOTH a BLUETOOTH_ADMIN zůstávají v manifestu pro kompatibilitu s API < 31, ale pro API 31+ jsou ignorována — Google vyžaduje explicitní uvedení nových oprávnění.
// Vyžádání Bluetooth oprávnění na Androidu 12+
import android.Manifest
import android.content.pm.PackageManager
import android.os.Build
import androidx.core.content.ContextCompat
class PermissionHelper(context: Context) {
fun getRequiredPermissions(): Array<String> {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
// Android 12+: BLE skenování
arrayOf(
Manifest.permission.BLUETOOTH_SCAN,
Manifest.permission.BLUETOOTH_CONNECT,
Manifest.permission.BLUETOOTH_ADVERTISE
)
} else {
// Android 6-11: BLE skenování
arrayOf(
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.BLUETOOTH,
Manifest.permission.BLUETOOTH_ADMIN
)
}
}
// Zkontrolovat všechna oprávnění
fun hasPermissions(context: Context): Boolean {
return getRequiredPermissions().all { permission ->
ContextCompat.checkSelfPermission(context, permission)
== PackageManager.PERMISSION_GRANTED
}
}
}
Třída PermissionHelper vrací správnou sadu oprávnění v závislosti na úrovni API. V Androidu 12+ se používají BLUETOOTH_SCAN, BLUETOOTH_CONNECT, BLUETOOTH_ADVERTISE bez polohy. V Androidu 6–11 je pro BLE skenování stále vyžadován ACCESS_FINE_LOCATION. Vývojář musí zohlednit oba scénáře při vyžadování oprávnění přes ActivityResultContracts nebo RxPermissions.
Kompletní příklad BLE aplikace v Kotlinu používající BluetoothAdapter pro skenování, připojení a čtení dat BLE zařízení. Příklad zahrnuje kontrolu oprávnění, získání adaptéru, skenování přes BluetoothLeScanner a připojení přes BluetoothDevice.connectGatt.
// Plný BLE manažer v Kotlinu
class BLEManager(private val context: Context) {
private val bluetoothManager: BluetoothManager =
context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
private val adapter: BluetoothAdapter? = bluetoothManager.adapter
private var scanner: BluetoothLeScanner? = adapter?.bluetoothLeScanner
private var gatt: BluetoothGatt? = null
// 1. Objevování služeb
fun canScan(): Boolean {
return adapter?.isEnabled == true
&& scanner != null
&& PermissionHelper(context).hasPermissions(context)
}
// 2. Skenování s filtrem
fun startScanning(callback: (BluetoothDevice, Int) -> Unit) {
if (!canScan()) return
val settings = ScanSettings.Builder()
.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
.setReportDelay(0)
.build()
scanner?.startScan(null, settings, object : ScanCallback() {
override fun onScanResult(callbackType: Int, result: ScanResult) {
callback(result.device, result.rssi)
}
})
}
// 3. Zastavit skenování
fun stopScanning() {
scanner?.stopScan(object : ScanCallback() {})
}
// 4. Připojit k BLE zařízení
fun connectToDevice(device: BluetoothDevice) {
if (adapter?.isEnabled != true) return
gatt = device.connectGatt(
context,
false,
object : BluetoothGattCallback() {
override fun onConnectionStateChange(gatt: BluetoothGatt, status: Int, newState: Int) {
if (newState == BluetoothProfile.STATE_CONNECTED) {
gatt.discoverServices()
}
}
override fun onServicesDiscovered(gatt: BluetoothGatt, status: Int) {
// Služby nalezeny, lze číst charakteristiky
}
},
BluetoothDevice.TRANSPORT_LE
)
}
// 5. Uvolnit zdroje
fun disconnect() {
gatt?.disconnect()
gatt?.close()
gatt = null
}
}
Manažer BLEManager spojuje kompletní BLE cyklus v Androidu: kontrolu adaptéru a oprávnění (canScan), skenování přes BluetoothLeScanner s ScanSettings (startScanning), připojení přes BluetoothDevice.connectGatt s TRANSPORT_LE (connectToDevice), uvolnění zdrojů (disconnect). Všechny BLE operace se provádějí na UI vlákně — Android volá callbacky BluetoothGattCallback na hlavním vlákně. Pro výkonné BLE úlohy se doporučuje přesunout GATT operace do vlákna HandlerThread na pozadí.
Často kladené otázky
BluetoothAdapter — třída představující místní Bluetooth adaptér zařízení s Androidem. Získává se přes BluetoothManager.getAdapter() (API 18+) nebo BluetoothAdapter.getDefaultAdapter(). Poskytuje metody zapnutí/vypnutí Bluetooth, skenování zařízení, správy viditelnosti a získání informací o adaptéru. Vrací null na zařízeních bez Bluetooth modulu.
Příčinou je absence Bluetooth rádia v zařízení. Typické pro Wi-Fi-only tablety, emulátor Androidu a Android TV bez Bluetooth. Zkontrolujte getDefaultAdapter() na null při spuštění aplikace a deaktivujte BLE funkce, pokud adaptér chybí. Alternativa — kontrola přes PackageManager.hasSystemFeature(FEATURE_BLUETOOTH_LE) pro přesnější určení.
BluetoothLeScanner (API 21+) — moderní API pro BLE skenování s podporou ScanFilter, ScanSettings a PendingIntent. startLeScan (API 18+) — zastaralá metoda BluetoothAdapter přijímající LeScanCallback s omezenou sadou dat. BluetoothLeScanner je doporučován Googlem pro všechny nové projekty, umožňuje filtrování podle UUID, konfiguraci režimu spotřeby energie a práci na pozadí přes PendingIntent.
Na Androidu 12+ (API 31) je pro BLE skenování vyžadován BLUETOOTH_SCAN, pro připojení — BLUETOOTH_CONNECT, pro reklamu — BLUETOOTH_ADVERTISE. Oprávnění k poloze ACCESS_FINE_LOCATION již není pro BLE vyžadováno. Na Androidu 6–11 je vyžadován ACCESS_FINE_LOCATION. Všechna oprávnění se vyžadují za běhu přes ActivityResultContracts.
Od Androidu 10+ je programové zapnutí Bluetooth bez systémového dialogu dostupné pouze systémovým aplikacím s oprávněním BLUETOOTH_PRIVILEGED. Běžné aplikace musí použít Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE) a startActivityForResult — uživatel potvrzuje zapnutí v systémovém dialogu. BLUETOOTH_ADMIN v manifestu nedává právo na enable() na Androidu 10+.
Závěr
Vyvineme mobilní aplikaci na klíč
IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.
Přečtěte si také