BluetoothAdapter — co to je, metody a správa Bluetooth v Androidu

Autor: IT Sectr Publikováno: 2026-07-16 Doba čtení: 10 min

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 — systémová třída Androidu pro správu místního Bluetooth adaptéru zařízení
  • getDefaultAdapter() — statická metoda pro získání instance; vrací null na zařízeních bez Bluetooth
  • getBluetoothLeScanner() — metoda přístupu k modernímu BLE skeneru (API 21+)
  • enable/disable — metody zapnutí a vypnutí Bluetooth rádia (vyžadují oprávnění BLUETOOTH_ADMIN)
  • startDiscovery/startLeScan — metody klasického a BLE skenování (LE Scan je zastaralý, používejte BluetoothLeScanner)

Co je BluetoothAdapter: podstata a získání instance

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.

kotlin
// 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.

Hlavní metody BluetoothAdapter: enable, disable, getState, getAddress

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+.

MetodaPopisPožadované oprávnění
enable()Zapnutí Bluetooth rádiaBLUETOOTH_ADMIN
disable()Vypnutí Bluetooth rádiaBLUETOOTH_ADMIN
getState()Aktuální stav adaptéruBLUETOOTH
getAddress()MAC adresa adaptéruBLUETOOTH + ACCESS_FINE_LOCATION (API 23+)
getScanMode()Režim viditelnosti zařízeníBLUETOOTH
setScanMode()Nastavení režimu viditelnostiBLUETOOTH_ADMIN

Skenování zařízení: startDiscovery a BluetoothLeScanner

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í.

kotlin
// 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: moderní API pro přístup k BluetoothAdapter

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í.

kotlin
// 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í Androidu pro práci s BluetoothAdapter

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:

OperaceAPI 23–30API 31+
Skenování BLEACCESS_FINE_LOCATIONBLUETOOTH_SCAN (bez polohy)
Připojení k BLEACCESS_FINE_LOCATIONBLUETOOTH_CONNECT
Reklama BLEACCESS_FINE_LOCATIONBLUETOOTH_ADVERTISE
Zapnutí/vypnutíBLUETOOTH_ADMINBLUETOOTH_ADMIN (systémové)
Získání MAC adresyACCESS_FINE_LOCATIONBLUETOOTH_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í.

kotlin
// 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 práce s BluetoothAdapter v Kotlinu

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.

kotlin
// 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

Co je BluetoothAdapter v Androidu?

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.

Proč BluetoothAdapter.getDefaultAdapter() vrací null?

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í.

Čím se liší BluetoothLeScanner od startLeScan?

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.

Jaká oprávnění jsou potřeba pro BLE na Androidu 12+?

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.

Lze Bluetooth zapnout programově bez dialogu?

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

  • BluetoothAdapter — vstupní bod pro všechny Bluetooth operace v Androidu, získává se přes BluetoothManager nebo getDefaultAdapter()
  • getState() a isEnabled — základní kontroly stavu Bluetooth rádia před jakýmikoli BLE operacemi
  • BluetoothLeScanner (API 21+) nahrazuje zastaralý startLeScan s podporou ScanFilter, ScanSettings a PendingIntent
  • BluetoothManager — moderní způsob získání BluetoothAdapter s podporou multiúčtových scénářů a Automotive
  • Oprávnění se vyvinula: ACCESS_FINE_LOCATION (API 23-30) → BLUETOOTH_SCAN/CONNECT/ADVERTISE (API 31+)
  • enable()/disable() — na Androidu 10+ pouze přes systémový dialog ACTION_REQUEST_ENABLE pro běžné aplikace
  • connectGatt — metoda BluetoothDevice pro navázání GATT spojení s BLE periferií přes BluetoothGattCallback

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í.

Prodiskutovat projekt

Přečtěte si také