BluetoothAdapter ist eine Android-Systemklasse, die den lokalen Bluetooth-Adapter eines Geräts darstellt. BluetoothAdapter ist der Einstiegspunkt für alle Bluetooth-Operationen unter Android: Einschalten des Funkgeräts (enable), Scannen von Geräten, Verwalten der Sichtbarkeit (setScanMode) und Abrufen von Adapterinformationen (getName, getAddress, getState). Die Klasse ist über BluetoothManager.getAdapter() (API 18+) oder BluetoothAdapter.getDefaultAdapter() verfügbar. Auf Geräten ohne Bluetooth-Modul gibt getDefaultAdapter() null zurück. Laut Android Developers, 2026 ist BluetoothAdapter ab API 5 eine Pflichtkomponente für jede BLE-Anwendung unter Android.
Wichtige Punkte
BluetoothAdapter repräsentiert den physischen Bluetooth-Adapter eines Android-Geräts. Jedes Gerät hat genau einen Adapter (Ausnahme: Android Automotive mit mehreren Bluetooth-Chips, das BluetoothManager.getAdapterList() verwendet). BluetoothAdapter kapselt den Funkstatus: STATE_OFF (0), STATE_TURNING_ON (1), STATE_ON (2), STATE_TURNING_OFF (3). Der Status wird über BroadcastReceiver auf ACTION_STATE_CHANGED verfolgt.
Das Abrufen einer BluetoothAdapter-Instanz ist der erste Schritt jeder BLE-Anwendung unter Android. Die empfohlene Methode ist über BluetoothManager.getAdapter() ab API 18+. Die Alternative ist die statische Methode BluetoothAdapter.getDefaultAdapter(), die ab API 5 funktioniert, aber weniger flexibel ist. Beide Methoden geben null zurück, wenn das Gerät kein Bluetooth-Modul hat (nur-WLAN-Tablets, Emulator). Die Null-Prüfung ist obligatorisch: Die Anwendung muss ordnungsgemäß beendet werden oder BLE-Funktionen deaktivieren.
// BluetoothAdapter abrufen (empfohlen)
import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothManager
import android.content.Context
class BluetoothHelper(context: Context) {
private val bluetoothAdapter: BluetoothAdapter?
init {
// Methode 1: über BluetoothManager (API 18+)
val manager = context.getSystemService(Context.BLUETOOTH_SERVICE)
as BluetoothManager?
bluetoothAdapter = manager?.adapter
// Methode 2: über statische Methode (API 5+)
// val adapter = BluetoothAdapter.getDefaultAdapter()
// Null-Prüfung
if (bluetoothAdapter == null) {
// Gerät unterstützt kein Bluetooth
}
}
// Bluetooth-Status prüfen
fun isBluetoothEnabled(): Boolean {
return bluetoothAdapter?.isEnabled == true
}
// Adapterinformationen abrufen
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")
)
}
}
Die Klasse BluetoothHelper demonstriert das Abrufen von BluetoothAdapter über BluetoothManager mit einer anschließenden Null-Prüfung. isBluetoothEnabled prüft isEnabled — eine obligatorische Bedingung vor allen BLE-Operationen. getAdapterInfo gibt Gerätename, MAC-Adresse, Status und Sichtbarkeitsmodus zurück. Wichtig: Unter Android 10+ (API 29+) gibt der Systemdienst eine gefälschte MAC-Adresse (02:00:00:00:00:00) zurück, wenn die App keine BLUETOOTH_ADMIN- und ACCESS_FINE_LOCATION-Berechtigungen hat.
BluetoothAdapter bietet Methoden zur Steuerung des Bluetooth-Funkgeräts. enable() und disable() schalten Bluetooth ein und aus. Beide Methoden erfordern die BLUETOOTH_ADMIN-Berechtigung und werden asynchron ausgeführt: Nach dem Aufruf von enable() startet das System den Einschaltvorgang des Funkgeräts, und der Status wird über BroadcastReceiver mit der Aktion BluetoothAdapter.ACTION_STATE_CHANGED verfolgt. Unter Android 10+ erfordern enable() und disable() zusätzliche Systemrechte — normale Apps können Bluetooth nicht programmatisch ohne Benutzerdialog steuern.
getState() gibt den aktuellen Adapterstatus zurück: STATE_OFF (10), STATE_TURNING_ON (11), STATE_ON (12), STATE_TURNING_OFF (13). getAddress() gibt die MAC-Adresse des Bluetooth-Adapters zurück. Unter Android 6+ ist ACCESS_FINE_LOCATION (oder ACCESS_COARSE_LOCATION für API 31+) erforderlich, um die MAC-Adresse anzufordern. Unter Android 10+ gibt getAddress() die konstante Adresse 02:00:00:00:00:00 zurück — die echte Adresse ist über die öffentliche API nicht verfügbar.
getScanMode() bestimmt den Sichtbarkeitsmodus des Adapters: SCAN_MODE_NONE (unsichtbar), SCAN_MODE_CONNECTABLE (sichtbar für verbundene Geräte), SCAN_MODE_CONNECTABLE_DISCOVERABLE (für alle sichtbar). Der Sichtbarkeitsmodus ist aus Sicherheitsgründen zeitlich begrenzt (normalerweise 60–300 Sekunden). Das Setzen des Modus über setScanMode() erfordert BLUETOOTH_ADMIN und Systemberechtigung unter Android 10+.
| Methode | Beschreibung | Erforderliche Berechtigung |
|---|---|---|
| enable() | Bluetooth-Funkgerät einschalten | BLUETOOTH_ADMIN |
| disable() | Bluetooth-Funkgerät ausschalten | BLUETOOTH_ADMIN |
| getState() | Aktueller Adapterstatus | BLUETOOTH |
| getAddress() | MAC-Adresse des Adapters | BLUETOOTH + ACCESS_FINE_LOCATION (API 23+) |
| getScanMode() | Sichtbarkeitsmodus des Geräts | BLUETOOTH |
| setScanMode() | Sichtbarkeitsmodus setzen | BLUETOOTH_ADMIN |
BluetoothAdapter unterstützt zwei Arten des Scannens. Das klassische Bluetooth-Scannen (BR/EDR) wird über startDiscovery() gestartet — es erkennt Bluetooth-Geräte aller Art, einschließlich Telefone und Headsets. Ergebnisse werden über BroadcastReceiver mit der Aktion BluetoothDevice.ACTION_FOUND zurückgegeben. startDiscovery() läuft 12 Sekunden und kann durch Aufruf von cancelDiscovery() abgebrochen werden. Diese Methode ist für BLE veraltet — verwenden Sie BluetoothLeScanner.
BLE-Scannen über BluetoothAdapter verwendet die veraltete Methode startLeScan(LeScanCallback). Ab API 21 empfiehlt Google die Verwendung von BluetoothLeScanner, das über BluetoothAdapter.getBluetoothLeScanner() abgerufen wird. BluetoothLeScanner bietet eine flexiblere API: Scan-Konfiguration über ScanSettings (Modus, Callback-Typ, Match-Modus), Filterung über ScanFilter (nach Dienst-UUID, Gerätename, MAC-Adresse) und Unterstützung für PendingIntent für Hintergrundscannen.
// Alte (veraltete) vs neue BLE-Scan-API
import android.bluetooth.BluetoothAdapter
import android.bluetooth.le.*
class BLEScanner(private val bluetoothAdapter: BluetoothAdapter?) {
// VERALTET: startLeScan (API 18+, API 21)
@Suppress("DEPRECATION")
fun legacyScan() {
bluetoothAdapter?.startLeScan { device, rssi, scanRecord ->
print("Found (LE Scan): $device.name, RSSI: $rssi")
}
}
// NEU: BluetoothLeScanner (API 21+)
fun modernScan() {
val scanner = bluetoothAdapter?.bluetoothLeScanner
?: return
// Scan-Einstellungen
val settings = ScanSettings.Builder()
.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
.setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES)
.setMatchMode(ScanSettings.MATCH_MODE_AGGRESSIVE)
.build()
// Nach Dienst filtern (Herzfrequenz-UUID)
val filters = listOf(
ScanFilter.Builder()
.setServiceUuid(ParcelUuid.fromString("0000180D-0000-1000-8000-00805F9B34FB"))
.build()
)
// Scan starten
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")
}
})
}
}
Die Klasse BLEScanner vergleicht das veraltete startLeScan mit dem modernen BluetoothLeScanner. In legacyScan empfängt LeScanCallback BluetoothDevice, RSSI und rohe scanRecord. In modernScan werden ScanSettings mit LOW_LATENCY-Modus (maximale Erkennungsgeschwindigkeit) und ScanFilter zum Filtern nach der Herzfrequenz-Dienst-UUID (0x180D) verwendet. ScanCallback stellt onScanResult mit einem ScanResult-Objekt mit erweiterten Informationen bereit: Name, RSSI, Werbedaten, Verbindungstyp.
BluetoothManager ist ein Android-Systemdienst, der in API 18 (Android 4.3) eingeführt wurde, zur Verwaltung von Bluetooth-Operationen. Vor API 18 war die einzige Möglichkeit, BluetoothAdapter zu erhalten, die statische Methode getDefaultAdapter(). BluetoothManager bietet: adapter — eine BluetoothAdapter-Instanz, getConnectedDevices() — eine Liste verbundener Geräte, getDevicesMatchingConnectionStates() — Filterung nach Status. BluetoothManager wird auch verwendet, um BluetoothLeScanner auf älteren APIs zu erhalten.
Vorteile von BluetoothManager gegenüber dem direkten Aufruf von BluetoothAdapter.getDefaultAdapter(): Die App hängt nicht von einem statischen Singleton ab, der Manager respektiert den Kontext (Activity/Application), was für Multi-Account-Szenarien von Android Enterprise wichtig ist. Auf Android Automotive mit mehreren Bluetooth-Chips gibt BluetoothManager.getAdapterList() alle verfügbaren Adapter zurück — BluetoothAdapter.getDefaultAdapter() gibt nur den ersten zurück.
// BluetoothManager für BLE verwenden
class BLEConnection(context: Context) {
private val bluetoothManager: BluetoothManager =
context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
private val adapter: BluetoothAdapter? = bluetoothManager.adapter
// Liste verbundener BLE-Geräte abrufen
fun getConnectedDevices(): List<BluetoothDevice> {
return bluetoothManager.getConnectedDevices(
BluetoothProfile.GATT
)
}
// Geräte nach Status filtern
fun getDevicesByState(states: IntArray): List<BluetoothDevice> {
return bluetoothManager.getDevicesMatchingConnectionStates(
BluetoothProfile.GATT, states
)
}
// BLE-Unterstützung auf Gerät prüfen
fun isBLESupported(): Boolean {
return adapter != null && context.packageManager
.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)
}
// Bluetooth-Einschalten über Systemdialog anfordern
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
}
}
Die Klasse BLEConnection verwendet BluetoothManager, um auf BluetoothAdapter zuzugreifen und die Liste der verbundenen GATT-Geräte abzurufen. isBLESupported prüft das Vorhandensein von BLE-Funk über PackageManager.hasSystemFeature(FEATURE_BLUETOOTH_LE) — eine wichtige Prüfung für Geräte mit Bluetooth Classic ohne BLE. requestEnableBluetooth zeigt den Systemdialog zum Einschalten von Bluetooth (ACTION_REQUEST_ENABLE), ohne BLUETOOTH_ADMIN-Berechtigung zu benötigen — dies ist der einzige legale Weg, Bluetooth unter Android 10+ ohne System-App einzuschalten.
Berechtigungen für BluetoothAdapter haben sich mit jeder Android-Version weiterentwickelt. Unter Android 6–11 (API 23–30) sind BLUETOOTH, BLUETOOTH_ADMIN und ACCESS_FINE_LOCATION für BLE-Scans obligatorisch. Unter Android 12+ (API 31+) hat Google die Berechtigungen aufgeteilt: ACCESS_FINE_LOCATION wird durch BLUETOOTH_SCAN (Scannen), BLUETOOTH_CONNECT (Verbindung), BLUETOOTH_ADVERTISE (Werbung) ersetzt. Für die Erkennung von BLE-Geräten ist BLUETOOTH_SCAN ausreichend, Standort wird nicht benötigt.
Berechtigungstabelle nach Android-Version:
| Operation | API 23–30 | API 31+ |
|---|---|---|
| BLE-Scan | ACCESS_FINE_LOCATION | BLUETOOTH_SCAN (ohne Standort) |
| BLE-Verbindung | ACCESS_FINE_LOCATION | BLUETOOTH_CONNECT |
| BLE-Werbung | ACCESS_FINE_LOCATION | BLUETOOTH_ADVERTISE |
| Ein-/Ausschalten | BLUETOOTH_ADMIN | BLUETOOTH_ADMIN (System) |
| MAC-Adresse abrufen | ACCESS_FINE_LOCATION | BLUETOOTH_CONNECT (gefälschte Adresse) |
Unter Android 12+ sind alle Bluetooth-Berechtigungen Laufzeitberechtigungen — sie müssen zur Laufzeit über ActivityResultContracts.RequestMultiplePermissions angefordert werden. BLUETOOTH_SCAN und BLUETOOTH_ADVERTISE gehören zur Gruppe NEARBY_DEVICES, BLUETOOTH_CONNECT gehört zur selben Gruppe. Die Berechtigungen BLUETOOTH und BLUETOOTH_ADMIN bleiben aus Kompatibilitätsgründen mit API < 31 im Manifest, werden aber für API 31+ ignoriert — Google verlangt die explizite Angabe der neuen Berechtigungen.
// Bluetooth-Berechtigungen unter Android 12+ anfordern
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-
arrayOf(
Manifest.permission.BLUETOOTH_SCAN,
Manifest.permission.BLUETOOTH_CONNECT,
Manifest.permission.BLUETOOTH_ADVERTISE
)
} else {
// Android 6-11: BLE
arrayOf(
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.BLUETOOTH,
Manifest.permission.BLUETOOTH_ADMIN
)
}
}
// Alle Berechtigungen prüfen
fun hasPermissions(context: Context): Boolean {
return getRequiredPermissions().all { permission ->
ContextCompat.checkSelfPermission(context, permission)
== PackageManager.PERMISSION_GRANTED
}
}
}
Die Klasse PermissionHelper gibt den korrekten Satz von Berechtigungen je nach API-Level zurück. Unter Android 12+ werden BLUETOOTH_SCAN, BLUETOOTH_CONNECT, BLUETOOTH_ADVERTISE ohne Standort verwendet. Unter Android 6–11 ist für BLE-Scans weiterhin ACCESS_FINE_LOCATION erforderlich. Der Entwickler muss beide Szenarien berücksichtigen, wenn er Berechtigungen über ActivityResultContracts oder RxPermissions anfordert.
Vollständiges Beispiel einer BLE-Anwendung in Kotlin, die BluetoothAdapter zum Scannen, Verbinden und Lesen von Daten eines BLE-Geräts verwendet. Das Beispiel umfasst die Berechtigungsprüfung, das Abrufen des Adapters, das Scannen über BluetoothLeScanner und die Verbindung über BluetoothDevice.connectGatt.
// Vollständiger BLE-Manager in Kotlin
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. Dienst-Erkennung
fun canScan(): Boolean {
return adapter?.isEnabled == true
&& scanner != null
&& PermissionHelper(context).hasPermissions(context)
}
// 2. mit Filter
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. Scannen beenden
fun stopScanning() {
scanner?.stopScan(object : ScanCallback() {})
}
// 4. Mit BLE-Gerät verbinden
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) {
// Dienste gefunden, kann Merkmale lesen
}
},
BluetoothDevice.TRANSPORT_LE
)
}
// 5. Ressourcen freigeben
fun disconnect() {
gatt?.disconnect()
gatt?.close()
gatt = null
}
}
Die Klasse BLEManager vereinheitlicht den vollständigen BLE-Zyklus unter Android: Überprüfung von Adapter und Berechtigungen (canScan), Scannen über BluetoothLeScanner mit ScanSettings (startScanning), Verbinden über BluetoothDevice.connectGatt mit TRANSPORT_LE (connectToDevice) und Freigeben von Ressourcen (disconnect). Alle BLE-Operationen werden im UI-Thread ausgeführt — Android ruft BluetoothGattCallback-Rückrufe im Hauptthread auf. Für leistungskritische BLE-Aufgaben wird empfohlen, GATT-Operationen auf einen Hintergrund-HandlerThread auszulagern.
Häufig gestellte Fragen
BluetoothAdapter ist eine Klasse, die den lokalen Bluetooth-Adapter eines Android-Geräts darstellt. Sie wird über BluetoothManager.getAdapter() (API 18+) oder BluetoothAdapter.getDefaultAdapter() abgerufen. Sie bietet Methoden zum Ein-/Ausschalten von Bluetooth, Scannen von Geräten, Verwalten der Sichtbarkeit und Abrufen von Adapterinformationen. Gibt null auf Geräten ohne Bluetooth-Modul zurück.
Der Grund ist das Fehlen eines Bluetooth-Funkgeräts auf dem Gerät. Typisch für WLAN-Only-Tablets, Android-Emulator und Android TV ohne Bluetooth. Überprüfen Sie getDefaultAdapter() beim App-Start auf null und deaktivieren Sie BLE-Funktionen, wenn der Adapter fehlt. Eine Alternative ist die Überprüfung über PackageManager.hasSystemFeature(FEATURE_BLUETOOTH_LE) für eine genauere Erkennung.
BluetoothLeScanner (API 21+) ist die moderne API für BLE-Scans mit Unterstützung für ScanFilter, ScanSettings und PendingIntent. startLeScan (API 18+) ist eine veraltete BluetoothAdapter-Methode, die LeScanCallback mit einem begrenzten Datensatz akzeptiert. Google empfiehlt BluetoothLeScanner für alle neuen Projekte, ermöglicht das Filtern nach UUID, das Konfigurieren des Stromverbrauchsmodus und den Hintergrundbetrieb über PendingIntent.
Unter Android 12+ (API 31) erfordert BLE-Scannen BLUETOOTH_SCAN, Verbinden erfordert BLUETOOTH_CONNECT und Werbung erfordert BLUETOOTH_ADVERTISE. Die Standortberechtigung ACCESS_FINE_LOCATION wird für BLE nicht mehr benötigt. Unter Android 6–11 ist ACCESS_FINE_LOCATION erforderlich. Alle Berechtigungen werden zur Laufzeit über ActivityResultContracts angefordert.
Unter Android 10+ ist das programmatische Einschalten von Bluetooth ohne Systemdialog nur für System-Apps mit BLUETOOTH_PRIVILEGED-Berechtigung verfügbar. Normale Apps müssen Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE) und startActivityForResult verwenden — der Benutzer bestätigt das Einschalten im Systemdialog. BLUETOOTH_ADMIN im Manifest gewährt unter Android 10+ keine enable()-Rechte.
Zusammenfassung
Wir entwickeln eine mobile Applikation schlüsselfertig
IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.
Lesen Sie auch