BluetoothAdapter — apa itu, metode dan pengelolaan Bluetooth di Android

Penulis: IT Sectr Diterbitkan: 2026-07-16 Waktu membaca: 10 mnt

BluetoothAdapter — kelas sistem Android yang mewakili adaptor Bluetooth lokal perangkat. BluetoothAdapter adalah titik masuk untuk semua operasi Bluetooth di Android: menyalakan radio (enable), memindai perangkat, mengelola visibilitas (setScanMode), mendapatkan informasi tentang adaptor (getName, getAddress, getState). Kelas tersedia melalui BluetoothManager.getAdapter() (API 18+) atau BluetoothAdapter.getDefaultAdapter(). Pada perangkat tanpa modul Bluetooth, getDefaultAdapter() mengembalikan null. Menurut Android Developers, 2026, BluetoothAdapter adalah komponen wajib untuk setiap aplikasi BLE di Android, mulai dari API 5.

Poin utama

  • BluetoothAdapter — kelas sistem Android untuk mengelola adaptor Bluetooth lokal perangkat
  • getDefaultAdapter() — metode statis untuk mendapatkan instance; mengembalikan null pada perangkat tanpa Bluetooth
  • getBluetoothLeScanner() — metode akses ke pemindai BLE modern (API 21+)
  • enable/disable — metode menyalakan dan mematikan radio Bluetooth (memerlukan izin BLUETOOTH_ADMIN)
  • startDiscovery/startLeScan — metode pemindaian klasik dan BLE (LE Scan sudah usang, gunakan BluetoothLeScanner)

Apa itu BluetoothAdapter: esensi dan mendapatkan instance

BluetoothAdapter mewakili adaptor Bluetooth fisik perangkat Android. Setiap perangkat memiliki tepat satu adaptor (pengecualian — Android Automotive dengan beberapa chip Bluetooth, di mana BluetoothManager.getAdapterList() digunakan). BluetoothAdapter mengenkapsulasi status radio: STATE_OFF (0), STATE_TURNING_ON (1), STATE_ON (2), STATE_TURNING_OFF (3). Status dilacak melalui BroadcastReceiver pada ACTION_STATE_CHANGED.

Mendapatkan instance BluetoothAdapter adalah langkah pertama setiap aplikasi BLE di Android. Metode yang direkomendasikan — melalui BluetoothManager.getAdapter() dari API 18+. Alternatif — metode statis BluetoothAdapter.getDefaultAdapter(), yang berfungsi dari API 5 tetapi kurang fleksibel. Kedua metode mengembalikan null jika perangkat tidak memiliki modul Bluetooth (tablet Wi-Fi-only, emulator). Pemeriksaan null wajib dilakukan: aplikasi harus menyelesaikan dirinya dengan benar atau menonaktifkan fungsi BLE.

kotlin
// Mendapatkan BluetoothAdapter (direkomendasikan)
import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothManager
import android.content.Context

class BluetoothHelper(context: Context) {

    private val bluetoothAdapter: BluetoothAdapter?

    init {
        // Metode 1: melalui BluetoothManager (API 18+)
        val manager = context.getSystemService(Context.BLUETOOTH_SERVICE)
                as BluetoothManager?
        bluetoothAdapter = manager?.adapter

        // Metode 2: melalui metode statis (API 5+)
        // val adapter = BluetoothAdapter.getDefaultAdapter()

        // Pemeriksaan null
        if (bluetoothAdapter == null) {
            // Perangkat tidak mendukung Bluetooth
        }
    }

    // Periksa status Bluetooth
    fun isBluetoothEnabled(): Boolean {
        return bluetoothAdapter?.isEnabled == true
    }

    // Dapatkan informasi adaptor
    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")
        )
    }
}

Kelas BluetoothHelper menunjukkan cara mendapatkan BluetoothAdapter melalui BluetoothManager dengan pemeriksaan null berikutnya. isBluetoothEnabled memeriksa isEnabled — kondisi wajib sebelum operasi BLE apa pun. getAdapterInfo mengembalikan nama perangkat, alamat MAC, status dan mode visibilitas. Penting: pada Android 10+ (API 29+) layanan sistem mengembalikan alamat MAC palsu (02:00:00:00:00:00) jika aplikasi tidak memiliki izin BLUETOOTH_ADMIN dan ACCESS_FINE_LOCATION.

Metode utama BluetoothAdapter: enable, disable, getState, getAddress

BluetoothAdapter menyediakan metode untuk mengelola radio Bluetooth. enable() dan disable() menyalakan dan mematikan Bluetooth. Kedua metode memerlukan izin BLUETOOTH_ADMIN dan dijalankan secara asinkron: setelah pemanggilan enable(), sistem memulai proses menyalakan radio, status dilacak melalui BroadcastReceiver dengan aksi BluetoothAdapter.ACTION_STATE_CHANGED. Sejak Android 10+, enable() dan disable() memerlukan izin sistem tambahan — aplikasi biasa tidak dapat mengelola Bluetooth secara terprogram tanpa dialog pengguna.

getState() mengembalikan status adaptor saat ini: STATE_OFF (10), STATE_TURNING_ON (11), STATE_ON (12), STATE_TURNING_OFF (13). getAddress() mengembalikan alamat MAC adaptor Bluetooth. Pada Android 6+, untuk meminta alamat MAC diperlukan ACCESS_FINE_LOCATION (atau ACCESS_COARSE_LOCATION untuk API 31+). Pada Android 10+, getAddress() mengembalikan alamat konstan 02:00:00:00:00:00 — alamat asli tidak tersedia melalui API publik.

getScanMode() menentukan mode visibilitas adaptor: SCAN_MODE_NONE (tidak terlihat), SCAN_MODE_CONNECTABLE (terlihat untuk yang terhubung), SCAN_MODE_CONNECTABLE_DISCOVERABLE (terlihat untuk semua). Mode visibilitas dibatasi waktu (biasanya 60–300 detik) untuk keamanan. Mengatur mode melalui setScanMode() memerlukan BLUETOOTH_ADMIN dan izin sistem pada Android 10+.

MetodeDeskripsiIzin yang diperlukan
enable()Menyalakan radio BluetoothBLUETOOTH_ADMIN
disable()Mematikan radio BluetoothBLUETOOTH_ADMIN
getState()Status adaptor saat iniBLUETOOTH
getAddress()Alamat MAC adaptorBLUETOOTH + ACCESS_FINE_LOCATION (API 23+)
getScanMode()Mode visibilitas perangkatBLUETOOTH
setScanMode()Mengatur mode visibilitasBLUETOOTH_ADMIN

Memindai perangkat: startDiscovery dan BluetoothLeScanner

BluetoothAdapter mendukung dua jenis pemindaian. Pemindaian Bluetooth klasik (BR/EDR) dimulai melalui startDiscovery() — mendeteksi perangkat Bluetooth dari semua jenis, termasuk telepon dan headset. Hasil dikembalikan melalui BroadcastReceiver dengan aksi BluetoothDevice.ACTION_FOUND. startDiscovery() bekerja selama 12 detik dan dapat dibatalkan dengan memanggil cancelDiscovery(). Metode ini sudah usang untuk BLE — gunakan BluetoothLeScanner.

Pemindaian BLE melalui BluetoothAdapter dilakukan dengan metode usang startLeScan(LeScanCallback). Mulai API 21, Google merekomendasikan penggunaan BluetoothLeScanner, yang diperoleh melalui BluetoothAdapter.getBluetoothLeScanner(). BluetoothLeScanner menyediakan API yang lebih fleksibel: konfigurasi pemindaian melalui ScanSettings (mode, callback type, match mode), pemfilteran melalui ScanFilter (berdasarkan UUID layanan, nama perangkat, alamat MAC) dan dukungan PendingIntent untuk pemindaian latar belakang.

kotlin
// API pemindaian BLE lama (usang) vs baru
import android.bluetooth.BluetoothAdapter
import android.bluetooth.le.*

class BLEScanner(private val bluetoothAdapter: BluetoothAdapter?) {

    // USANG: startLeScan (API 18+, API 21)
    @Suppress("DEPRECATION")
    fun legacyScan() {
        bluetoothAdapter?.startLeScan { device, rssi, scanRecord ->
            print("Found (LE Scan): $device.name, RSSI: $rssi")
        }
    }

    // BARU: BluetoothLeScanner (API 21+)
    fun modernScan() {
        val scanner = bluetoothAdapter?.bluetoothLeScanner
            ?: return

        // Pengaturan pemindaian
        val settings = ScanSettings.Builder()
            .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
            .setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES)
            .setMatchMode(ScanSettings.MATCH_MODE_AGGRESSIVE)
            .build()

        // Filter berdasarkan layanan (UUID detak jantung)
        val filters = listOf(
            ScanFilter.Builder()
                .setServiceUuid(ParcelUuid.fromString("0000180D-0000-1000-8000-00805F9B34FB"))
                .build()
        )

        // Mulai pemindaian
        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")
            }
        })
    }
}

Kelas BLEScanner membandingkan startLeScan yang usang dan BluetoothLeScanner modern. Di legacyScan, callback LeScanCallback menerima BluetoothDevice, RSSI dan scanRecord mentah. Di modernScan, ScanSettings digunakan dengan mode LOW_LATENCY (kecepatan deteksi maksimum) dan ScanFilter untuk memfilter berdasarkan UUID layanan detak jantung (Heart Rate Service 0x180D). ScanCallback menyediakan onScanResult dengan objek ScanResult yang berisi informasi luas: nama, RSSI, data iklan, jenis koneksi.

BluetoothManager: API modern untuk akses ke BluetoothAdapter

BluetoothManager — layanan sistem Android, diperkenalkan di API 18 (Android 4.3), untuk mengelola operasi Bluetooth. Sebelum API 18, satu-satunya cara untuk mendapatkan BluetoothAdapter adalah metode statis getDefaultAdapter(). BluetoothManager menyediakan: adapter — instance BluetoothAdapter, getConnectedDevices() — daftar perangkat terhubung, getDevicesMatchingConnectionStates() — pemfilteran berdasarkan status. BluetoothManager juga digunakan untuk mendapatkan BluetoothLeScanner pada API lama.

Keunggulan BluetoothManager dibandingkan panggilan langsung BluetoothAdapter.getDefaultAdapter(): aplikasi tidak bergantung pada singleton statis, manajer mempertimbangkan konteks (Activity/Application), yang penting untuk skenario multi-akun Android Enterprise. Pada Android Automotive dengan beberapa chip Bluetooth, BluetoothManager.getAdapterList() mengembalikan semua adaptor yang tersedia — BluetoothAdapter.getDefaultAdapter() hanya mengembalikan yang pertama.

kotlin
// Menggunakan BluetoothManager untuk BLE
class BLEConnection(context: Context) {

    private val bluetoothManager: BluetoothManager =
        context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager

    private val adapter: BluetoothAdapter? = bluetoothManager.adapter

    // Dapatkan daftar perangkat BLE yang terhubung
    fun getConnectedDevices(): List<BluetoothDevice> {
        return bluetoothManager.getConnectedDevices(
            BluetoothProfile.GATT
        )
    }

    // Filter perangkat berdasarkan status
    fun getDevicesByState(states: IntArray): List<BluetoothDevice> {
        return bluetoothManager.getDevicesMatchingConnectionStates(
            BluetoothProfile.GATT, states
        )
    }

    // Periksa dukungan BLE pada perangkat
    fun isBLESupported(): Boolean {
        return adapter != null && context.packageManager
            .hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)
    }

    // Minta menyalakan Bluetooth melalui dialog sistem
    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
    }
}

Kelas BLEConnection menggunakan BluetoothManager untuk akses ke BluetoothAdapter dan mendapatkan daftar perangkat GATT yang terhubung. isBLESupported memeriksa keberadaan radio BLE melalui PackageManager.hasSystemFeature(FEATURE_BLUETOOTH_LE) — pemeriksaan penting untuk perangkat dengan Bluetooth Classic tanpa BLE. requestEnableBluetooth menampilkan dialog sistem untuk menyalakan Bluetooth (ACTION_REQUEST_ENABLE), tanpa memerlukan izin BLUETOOTH_ADMIN — ini adalah satu-satunya cara legal untuk menyalakan Bluetooth di Android 10+ tanpa aplikasi sistem.

Izin Android untuk bekerja dengan BluetoothAdapter

Izin untuk BluetoothAdapter telah berevolusi dengan setiap versi Android. Pada Android 6–11 (API 23–30) untuk pemindaian BLE, BLUETOOTH, BLUETOOTH_ADMIN dan ACCESS_FINE_LOCATION wajib. Pada Android 12+ (API 31+) Google telah membagi izin: ACCESS_FINE_LOCATION digantikan oleh BLUETOOTH_SCAN (pemindaian), BLUETOOTH_CONNECT (koneksi), BLUETOOTH_ADVERTISE (iklan). Untuk mencari perangkat BLE, BLUETOOTH_SCAN sudah cukup, lokasi tidak diperlukan.

Tabel izin berdasarkan versi Android:

OperasiAPI 23–30API 31+
Pemindaian BLEACCESS_FINE_LOCATIONBLUETOOTH_SCAN (tanpa lokasi)
Koneksi BLEACCESS_FINE_LOCATIONBLUETOOTH_CONNECT
Iklan BLEACCESS_FINE_LOCATIONBLUETOOTH_ADVERTISE
Menyalakan/mematikanBLUETOOTH_ADMINBLUETOOTH_ADMIN (sistem)
Mendapatkan alamat MACACCESS_FINE_LOCATIONBLUETOOTH_CONNECT (alamat palsu)

Pada Android 12+, semua izin Bluetooth adalah izin runtime — harus diminta saat runtime melalui ActivityResultContracts.RequestMultiplePermissions. BLUETOOTH_SCAN dan BLUETOOTH_ADVERTISE termasuk dalam grup NEARBY_DEVICES, BLUETOOTH_CONNECT — grup yang sama. Izin BLUETOOTH dan BLUETOOTH_ADMIN tetap di manifes untuk kompatibilitas dengan API < 31, tetapi untuk API 31+ diabaikan — Google memerlukan penyebutan eksplisit izin baru.

kotlin
// Meminta izin Bluetooth di Android 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+: pemindaian BLE
            arrayOf(
                Manifest.permission.BLUETOOTH_SCAN,
                Manifest.permission.BLUETOOTH_CONNECT,
                Manifest.permission.BLUETOOTH_ADVERTISE
            )
        } else {
            // Android 6-11: pemindaian BLE
            arrayOf(
                Manifest.permission.ACCESS_FINE_LOCATION,
                Manifest.permission.BLUETOOTH,
                Manifest.permission.BLUETOOTH_ADMIN
            )
        }
    }

    // Periksa semua izin
    fun hasPermissions(context: Context): Boolean {
        return getRequiredPermissions().all { permission ->
            ContextCompat.checkSelfPermission(context, permission)
                    == PackageManager.PERMISSION_GRANTED
        }
    }
}

Kelas PermissionHelper mengembalikan set izin yang benar tergantung pada level API. Pada Android 12+, BLUETOOTH_SCAN, BLUETOOTH_CONNECT, BLUETOOTH_ADVERTISE digunakan tanpa lokasi. Pada Android 6–11 untuk pemindaian BLE masih diperlukan ACCESS_FINE_LOCATION. Pengembang harus mempertimbangkan kedua skenario saat meminta izin melalui ActivityResultContracts atau RxPermissions.

Contoh lengkap bekerja dengan BluetoothAdapter di Kotlin

Contoh lengkap aplikasi BLE di Kotlin yang menggunakan BluetoothAdapter untuk memindai, menghubungkan dan membaca data perangkat BLE. Contoh ini mencakup pemeriksaan izin, mendapatkan adaptor, pemindaian melalui BluetoothLeScanner dan koneksi melalui BluetoothDevice.connectGatt.

kotlin
// Manajer BLE lengkap di 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. Penemuan layanan
    fun canScan(): Boolean {
        return adapter?.isEnabled == true
                && scanner != null
                && PermissionHelper(context).hasPermissions(context)
    }

    // 2. Pemindaian dengan 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. Hentikan pemindaian
    fun stopScanning() {
        scanner?.stopScan(object : ScanCallback() {})
    }

    // 4. Hubungkan ke perangkat BLE
    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) {
                    // Layanan ditemukan, dapat membaca karakteristik
                }
            },
            BluetoothDevice.TRANSPORT_LE
        )
    }

    // 5. Lepaskan sumber daya
    fun disconnect() {
        gatt?.disconnect()
        gatt?.close()
        gatt = null
    }
}

Manajer BLEManager menggabungkan siklus BLE lengkap di Android: pemeriksaan adaptor dan izin (canScan), pemindaian melalui BluetoothLeScanner dengan ScanSettings (startScanning), koneksi melalui BluetoothDevice.connectGatt dengan TRANSPORT_LE (connectToDevice), pelepasan sumber daya (disconnect). Semua operasi BLE dijalankan di thread UI — Android memanggil callback BluetoothGattCallback di thread utama. Untuk tugas BLE yang produktif, disarankan untuk memindahkan operasi GATT ke HandlerThread latar belakang.

Pertanyaan yang sering diajukan

Apa itu BluetoothAdapter di Android?

BluetoothAdapter — kelas yang mewakili adaptor Bluetooth lokal perangkat Android. Diperoleh melalui BluetoothManager.getAdapter() (API 18+) atau BluetoothAdapter.getDefaultAdapter(). Menyediakan metode menyalakan/mematikan Bluetooth, memindai perangkat, mengelola visibilitas dan mendapatkan informasi tentang adaptor. Mengembalikan null pada perangkat tanpa modul Bluetooth.

Mengapa BluetoothAdapter.getDefaultAdapter() mengembalikan null?

Penyebabnya adalah tidak adanya radio Bluetooth pada perangkat. Karakteristik untuk tablet Wi-Fi-only, emulator Android dan Android TV tanpa Bluetooth. Periksa getDefaultAdapter() untuk null saat memulai aplikasi dan nonaktifkan fungsi BLE jika adaptor tidak ada. Alternatif — pemeriksaan melalui PackageManager.hasSystemFeature(FEATURE_BLUETOOTH_LE) untuk penentuan yang lebih akurat.

Apa perbedaan BluetoothLeScanner dengan startLeScan?

BluetoothLeScanner (API 21+) — API modern untuk pemindaian BLE dengan dukungan ScanFilter, ScanSettings dan PendingIntent. startLeScan (API 18+) — metode usang BluetoothAdapter yang menerima LeScanCallback dengan set data terbatas. BluetoothLeScanner direkomendasikan oleh Google untuk semua proyek baru, memungkinkan pemfilteran berdasarkan UUID, konfigurasi mode konsumsi daya dan bekerja di latar belakang melalui PendingIntent.

Izin apa yang diperlukan untuk BLE di Android 12+?

Di Android 12+ (API 31) untuk pemindaian BLE diperlukan BLUETOOTH_SCAN, untuk koneksi — BLUETOOTH_CONNECT, untuk iklan — BLUETOOTH_ADVERTISE. Izin lokasi ACCESS_FINE_LOCATION tidak lagi diperlukan untuk BLE. Di Android 6–11 diperlukan ACCESS_FINE_LOCATION. Semua izin diminta saat runtime melalui ActivityResultContracts.

Bisakah Bluetooth dinyalakan secara terprogram tanpa dialog?

Sejak Android 10+, menyalakan Bluetooth secara terprogram tanpa dialog sistem hanya tersedia untuk aplikasi sistem dengan izin BLUETOOTH_PRIVILEGED. Aplikasi biasa harus menggunakan Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE) dan startActivityForResult — pengguna mengonfirmasi penyalakan di dialog sistem. BLUETOOTH_ADMIN di manifes tidak memberikan hak enable() di Android 10+.

Kesimpulan

  • BluetoothAdapter — titik masuk untuk semua operasi Bluetooth di Android, diperoleh melalui BluetoothManager atau getDefaultAdapter()
  • getState() dan isEnabled — pemeriksaan dasar status radio Bluetooth sebelum operasi BLE
  • BluetoothLeScanner (API 21+) menggantikan startLeScan yang usang dengan dukungan ScanFilter, ScanSettings dan PendingIntent
  • BluetoothManager — cara modern mendapatkan BluetoothAdapter dengan dukungan skenario multi-akun dan Automotive
  • Izin telah berevolusi: ACCESS_FINE_LOCATION (API 23-30) → BLUETOOTH_SCAN/CONNECT/ADVERTISE (API 31+)
  • enable()/disable() — di Android 10+ hanya melalui dialog sistem ACTION_REQUEST_ENABLE untuk aplikasi biasa
  • connectGatt — metode BluetoothDevice untuk membuat koneksi GATT dengan periferal BLE melalui BluetoothGattCallback

Kami akan mengembangkan aplikasi seluler turnkey

IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.

Diskusikan proyek

Baca juga