Bluetooth Classic + BLE

Bluetooth Classic + BLE 

1. What is Bluetooth?

Bluetooth is a wireless communication technology used to exchange data between nearby devices.

In Android, Bluetooth APIs allow apps to connect with other Bluetooth devices and support point-to-point or multipoint wireless communication. Android supports both Bluetooth Classic and Bluetooth Low Energy / BLE. (Android Developers)

Android Phone
   |
   +---- Bluetooth Speaker
   +---- Smartwatch
   +---- Barcode Scanner
   +---- Printer
   +---- Car System
   +---- BLE Sensor

Simple meaning:

Bluetooth = wireless communication between nearby devices

---

2. Why Android Developers Use Bluetooth

Android developers use Bluetooth when the app needs to communicate with external hardware.

Common Android use cases:

Use CaseExample
Audio deviceSpeaker, headphone
PrintingBluetooth thermal printer
ScannerBarcode scanner
WearableSmartwatch, fitness band
IoTSmart lock, smart bulb
SensorHeart-rate, temperature, motion sensor
Enterprise deviceZebra scanner, handheld device

---

3. Types of Bluetooth in Android

There are mainly two important types for Android interviews:

Bluetooth
   |
   +-- Bluetooth Classic
   |
   +-- BLE / Bluetooth Low Energy

---

4. Bluetooth Classic

What is Bluetooth Classic?

Bluetooth Classic is the traditional Bluetooth communication model. It is mainly used when a device needs a stable or continuous connection.

Simple meaning:

Bluetooth Classic = pair device + connect + send/receive data continuously

Common Examples

Phone <-> Bluetooth Speaker
Phone <-> Bluetooth Printer
Phone <-> Barcode Scanner
Phone <-> Car Music System
Phone <-> Old Hardware Device

---

How Bluetooth Classic Works

Step 1: Check Bluetooth support
Step 2: Check Bluetooth is ON
Step 3: Request Bluetooth permission
Step 4: Find paired/discovered device
Step 5: Create BluetoothSocket
Step 6: Connect device
Step 7: Send/receive data using streams
Step 8: Close socket

---

Bluetooth Classic Diagram

Android App
   |
BluetoothAdapter
   |
BluetoothDevice
   |
BluetoothSocket
   |
InputStream / OutputStream
   |
External Bluetooth Device

---

Bluetooth Classic Implementation Flow

// Pseudocode only

val bluetoothManager = getSystemService(BluetoothManager::class.java)
val bluetoothAdapter = bluetoothManager.adapter

// 1. Check Bluetooth supported
if (bluetoothAdapter == null) {
    // Device does not support Bluetooth
}

// 2. Get paired devices
val pairedDevices = bluetoothAdapter.bondedDevices

// 3. Select target device
val device = pairedDevices.firstOrNull {
    it.name == "MyPrinter"
}

// 4. Connect using BluetoothSocket
val socket = device?.createRfcommSocketToServiceRecord(MY_UUID)
socket?.connect()

// 5. Send data
val outputStream = socket?.outputStream
outputStream?.write("Hello Printer".toByteArray())

// 6. Close socket
socket?.close()

---

Bluetooth Classic Pros

ProsExplanation
Stable connectionGood for continuous communication
Good data transferBetter than BLE for larger/continuous data
Common hardware supportPrinters, scanners, speakers
Stream-basedEasy to understand using input/output streams

---

Bluetooth Classic Cons

ConsExplanation
Higher battery usageConsumes more power than BLE
Pairing required mostlyUser may need to pair manually
Not ideal for sensorsSmall sensor data is better with BLE
Background limitationsNeed careful lifecycle handling

---

When to Use Bluetooth Classic

Use Bluetooth Classic when:

- Device needs continuous connection
- Device uses socket-based communication
- Device sends larger data
- Example: printer, scanner, speaker, car system

---

5. BLE: Bluetooth Low Energy

What is BLE?

BLE means Bluetooth Low Energy. It is designed for low-power communication and small data transfer.

Simple meaning:

BLE = low battery + small data + wearable/sensor communication

BLE uses GATT to send and receive small pieces of data called attributes over a BLE link. (Android Developers)

---

BLE Common Examples

Phone <-> Smartwatch
Phone <-> Fitness Band
Phone <-> Heart Rate Sensor
Phone <-> BLE Beacon
Phone <-> Smart Lock
Phone <-> Temperature Sensor
Phone <-> IoT Device

---

BLE Use Cases for Android Developer

Use CaseExample
Wearable deviceFitness band sends steps
Health deviceHeart-rate sensor sends BPM
BeaconIndoor location tracking
IoTSmart lock open/close
Asset trackingBLE tag attached to asset
EnterpriseBLE scanner/sensor in warehouse
Smart glassesUsually SDK-based, but BLE concept helps

---

6. BLE Roles

BLE has two important roles:

1. Central

The central device scans and connects.

Usually:

Android Phone = Central

2. Peripheral

The peripheral device advertises and provides data.

Usually:

Watch / Sensor / Beacon = Peripheral

---

BLE Role Diagram

Android Phone
Central Device
   |
   | scans nearby devices
   v
BLE Sensor / Watch
Peripheral Device
   |
   | advertises itself
   v
Available for connection

---

7. BLE Basic Flow

Android Phone
   |
Start BLE Scan
   |
Find BLE Device
   |
Stop Scan
   |
Connect GATT
   |
Discover Services
   |
Find Characteristic
   |
Read / Write / Subscribe
   |
Receive Data
Important point: Android BLE docs recommend stopping the scan as soon as the desired device is found and avoiding scan loops because continuous scanning drains battery. ([Android Developers][3])

---

8. What is GATT?

GATT means Generic Attribute Profile.

Simple meaning:

GATT = BLE data structure after connection

BLE data is organized like this:

GATT
   |
   +-- Service
          |
          +-- Characteristic
                  |
                  +-- Descriptor

---

GATT Terms

TermEasy Meaning
GATTBLE communication model
GATT ClientDevice requesting data, usually phone
GATT ServerDevice providing data, usually sensor/watch
ServiceGroup of related features
CharacteristicActual data value
DescriptorExtra information about characteristic
UUIDUnique ID for service/characteristic
NotificationDevice automatically sends updates
IndicationNotification with acknowledgement

A GATT characteristic is the basic data element inside a GATT service and contains a value plus optional descriptors. (Android Developers)

---

GATT Example

Suppose we have a heart-rate band.

Heart Rate Band
   |
   +-- Heart Rate Service
   |      |
   |      +-- Heart Rate Measurement Characteristic
   |
   +-- Battery Service
          |
          +-- Battery Level Characteristic

Simple meaning:

Service = feature group
Characteristic = actual value

Example:

Battery Service
   |
Battery Level Characteristic = 85%

---

9. BLE Read, Write, Notification

Read

Phone asks device for data.

Phone: What is your battery level?
Device: 85%

Write

Phone sends command/data to device.

Phone: Turn LED ON
Device: LED turned ON

Notification

Device automatically sends updates.

Heart-rate sensor:
80 BPM
82 BPM
84 BPM

---

Diagram

Read:
Phone -------- request --------> BLE Device
Phone <------- response ------- BLE Device

Write:
Phone -------- command -------> BLE Device

Notification:
Phone subscribes first
BLE Device ---- updates -----> Phone

---

10. Bluetooth Classic vs BLE Comparison

TopicBluetooth ClassicBLE
Full formBluetooth ClassicBluetooth Low Energy
Best forContinuous communicationLow-power small data
Battery usageHigherLower
Data transferLarger/continuous dataSmall/sensor data
Android API styleBluetoothSocketBluetoothGatt
Common exampleSpeaker, printer, scannerWatch, sensor, beacon
ConnectionPair/connect/socketScan/connect/GATT
Data modelStream-basedService/characteristic-based
Interview keywordSocket, streamGATT, service, characteristic

---

Easy Memory Trick

Bluetooth Classic = Socket + Stream
BLE               = Scan + GATT + Characteristic

---

11. Android Bluetooth Permissions

Android 12/API 31 and Above

For Android 12 and above, Android introduced these Bluetooth permissions:
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />

Android 12 introduced BLUETOOTH_SCAN, BLUETOOTH_ADVERTISE, and BLUETOOTH_CONNECT permissions to make Bluetooth device interaction clearer, especially for apps that do not require location access. (Android Developers)

---

Older Android Versions

For Android 11/API 30 and below:

<uses-permission
    android:name="android.permission.BLUETOOTH"
    android:maxSdkVersion="30" />

<uses-permission
    android:name="android.permission.BLUETOOTH_ADMIN"
    android:maxSdkVersion="30" />

Android’s Bluetooth permission guide recommends using android:maxSdkVersion="30" for legacy Bluetooth permissions when targeting Android 12 or higher. (Android Developers)

---

Permission Meaning

PermissionMeaning
BLUETOOTH_SCANScan nearby Bluetooth/BLE devices
BLUETOOTH_CONNECTConnect or communicate with devices
BLUETOOTH_ADVERTISEMake phone advertise as BLE device
BLUETOOTHLegacy Bluetooth permission
BLUETOOTH_ADMINLegacy discovery/admin permission
ACCESS_FINE_LOCATIONMay be needed if scan result is used for location

---

12. BLE Implementation Steps in Android

Full Implementation Flow

1. Add permissions in manifest
2. Request runtime permission
3. Check Bluetooth support
4. Check Bluetooth enabled
5. Start BLE scan
6. Filter required device
7. Stop scan
8. Connect using connectGatt()
9. Discover services
10. Find service UUID
11. Find characteristic UUID
12. Read/write/subscribe
13. Handle disconnect
14. Close BluetoothGatt
To connect to a BLE device, Android uses `connectGatt()`. The Android app acts as the GATT client, and results such as connection status are delivered through `BluetoothGattCallback`. ([Android Developers][7])

After connecting to the GATT server, the app should perform service discovery to learn the available services, characteristics, and descriptors. (Android Developers)

---

13. BLE Scanner Pseudocode

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

    private val bluetoothAdapter =
        bluetoothManager.adapter

    private val scanner =
        bluetoothAdapter.bluetoothLeScanner

    private var scanCallback: ScanCallback? = null

    fun startScan() {
        // Check BLUETOOTH_SCAN permission before this

        scanCallback = object : ScanCallback() {

            override fun onScanResult(
                callbackType: Int,
                result: ScanResult
            ) {
                val device = result.device
                val deviceName = device.name ?: "Unknown"

                Log.d("BLE", "Found device: $deviceName")

                if (deviceName.contains("MyDevice", ignoreCase = true)) {
                    stopScan()
                    connectDevice(device)
                }
            }

            override fun onScanFailed(errorCode: Int) {
                Log.e("BLE", "Scan failed: $errorCode")
            }
        }

        scanner.startScan(scanCallback)
    }

    fun stopScan() {
        scanCallback?.let {
            scanner.stopScan(it)
        }
        scanCallback = null
    }

    private fun connectDevice(device: BluetoothDevice) {
        // Connect using GATT
    }
}

---

14. BLE GATT Connection Pseudocode

class BleConnectionManager(
    private val context: Context
) {
    private var bluetoothGatt: BluetoothGatt? = null

    fun connect(device: BluetoothDevice) {
        // Check BLUETOOTH_CONNECT permission before this

        bluetoothGatt = device.connectGatt(
            context,
            false,
            gattCallback
        )
    }

    private val gattCallback = object : BluetoothGattCallback() {

        override fun onConnectionStateChange(
            gatt: BluetoothGatt,
            status: Int,
            newState: Int
        ) {
            when (newState) {
                BluetoothProfile.STATE_CONNECTED -> {
                    Log.d("BLE", "Connected")
                    gatt.discoverServices()
                }

                BluetoothProfile.STATE_DISCONNECTED -> {
                    Log.d("BLE", "Disconnected")
                    close()
                }
            }
        }

        override fun onServicesDiscovered(
            gatt: BluetoothGatt,
            status: Int
        ) {
            if (status == BluetoothGatt.GATT_SUCCESS) {
                val service = gatt.getService(
                    UUID.fromString("SERVICE_UUID")
                )

                val characteristic = service?.getCharacteristic(
                    UUID.fromString("CHARACTERISTIC_UUID")
                )

                if (characteristic != null) {
                    gatt.readCharacteristic(characteristic)
                }
            }
        }

        override fun onCharacteristicRead(
            gatt: BluetoothGatt,
            characteristic: BluetoothGattCharacteristic,
            value: ByteArray,
            status: Int
        ) {
            if (status == BluetoothGatt.GATT_SUCCESS) {
                val data = value.decodeToString()
                Log.d("BLE", "Received data: $data")
            }
        }
    }

    fun close() {
        bluetoothGatt?.close()
        bluetoothGatt = null
    }
}

---

15. Android Developer Architecture

For 11+ years experience, explain using architecture, not only APIs.
UI Layer
Activity / Fragment / Compose
        |
ViewModel
        |
Use Case
        |
Repository Interface
        |
Repository Implementation
        |
BLE / Bluetooth Data Source
        |
Android Bluetooth APIs

---

Package Structure Example

feature_bluetooth/
   presentation/
      BluetoothScreen.kt
      BluetoothViewModel.kt
      BluetoothUiState.kt

   domain/
      repository/
         BluetoothRepository.kt

      usecase/
         StartBleScanUseCase.kt
         ConnectBleDeviceUseCase.kt
         ReadBleDataUseCase.kt
         DisconnectBleUseCase.kt

   data/
      BluetoothRepositoryImpl.kt
      BleScannerDataSource.kt
      BleGattDataSource.kt

---

UI State Example

sealed interface BluetoothUiState {
    data object Idle : BluetoothUiState
    data object PermissionRequired : BluetoothUiState
    data object Scanning : BluetoothUiState
    data object Connecting : BluetoothUiState
    data object Connected : BluetoothUiState
    data class DataReceived(val value: String) : BluetoothUiState
    data class Error(val message: String) : BluetoothUiState
}

---

ViewModel Example

class BluetoothViewModel(
    private val startBleScanUseCase: StartBleScanUseCase,
    private val connectBleDeviceUseCase: ConnectBleDeviceUseCase
) : ViewModel() {

    private val _uiState =
        MutableStateFlow<BluetoothUiState>(BluetoothUiState.Idle)

    val uiState: StateFlow<BluetoothUiState> = _uiState

    fun startScan() {
        viewModelScope.launch {
            try {
                _uiState.value = BluetoothUiState.Scanning

                val device = startBleScanUseCase()

                _uiState.value = BluetoothUiState.Connecting

                connectBleDeviceUseCase(device)

                _uiState.value = BluetoothUiState.Connected
            } catch (e: Exception) {
                _uiState.value =
                    BluetoothUiState.Error(e.message ?: "Bluetooth error")
            }
        }
    }
}

---

16. Pros and Cons

Bluetooth Classic Pros and Cons

ProsCons
Good for continuous dataHigher battery usage
Suitable for printers/scanners/audioPairing usually required
Stream-based communicationNot ideal for small sensor updates
Mature device supportBackground handling can be tricky

---

BLE Pros and Cons

ProsCons
Low battery usageSmaller data transfer
Best for sensors/wearablesMore complex GATT structure
Supports notificationsConnection may be unstable
Good for IoT/beaconsNeed UUID/service knowledge
Can scan nearby devicesScanning drains battery if misused

---

17. Important Best Practices

1. Always check runtime permissions.
2. Stop BLE scan after finding device.
3. Use scan timeout.
4. Do not scan continuously in loop.
5. Close BluetoothGatt when disconnected.
6. Handle connection failure.
7. Handle null device name.
8. Prefer filtering by service UUID if possible.
9. Avoid logging sensitive device data.
10. Keep Bluetooth code out of Activity/ViewModel.

---

18. Common Problems and Fixes

ProblemPossible ReasonFix
BLE scan not workingPermission missingCheck BLUETOOTH_SCAN
Connect failsPermission missingCheck BLUETOOTH_CONNECT
Device name nullAdvertisement does not include nameUse UUID/filter/address
Battery drainScan running too longStop scan after timeout
Services emptyDiscovery not doneCall discoverServices()
No updatesNotification not enabledEnable characteristic notification
Memory leakGATT not closedCall close()
Works on Android 10 but fails on 12+New permissions missingAdd runtime Bluetooth permissions

---

19. Interview Questions and Answers

Q1. What is Bluetooth Classic?

Answer:

> Bluetooth Classic is used for stable or continuous communication with devices like speakers, printers, scanners, and car systems. In Android, it commonly uses BluetoothSocket and input/output streams for data transfer.

---

Q2. What is BLE?

Answer:

> BLE stands for Bluetooth Low Energy. It is used for low-power communication with wearables, sensors, beacons, and IoT devices. In Android, BLE works using scanning, GATT connection, services, and characteristics.

---

Q3. Difference between Bluetooth Classic and BLE?

Answer:

> Bluetooth Classic is better for continuous or larger data transfer, like audio or printing. BLE is better for low-power small data transfer, like heart-rate sensors, fitness bands, and beacons. Classic uses socket-style communication, while BLE uses GATT services and characteristics.

---

Q4. What is GATT?

Answer:

> GATT is the BLE communication model. It organizes data into services and characteristics. The phone usually acts as GATT client, and the BLE device acts as GATT server.

---

Q5. What is a BLE service?

Answer:

> A BLE service is a group of related features. For example, a heart-rate device can have Heart Rate Service and Battery Service.

---

Q6. What is a BLE characteristic?

Answer:

> A characteristic is the actual data value inside a BLE service. For example, Battery Level is a characteristic inside Battery Service.

---

Q7. Why should we stop BLE scanning?

Answer:

> BLE scanning consumes battery. So we should stop scanning after finding the target device or after a timeout.

---

Q8. What permissions are needed for Bluetooth on Android 12+?

Answer:

> Android 12+ uses BLUETOOTH_SCAN, BLUETOOTH_CONNECT, and BLUETOOTH_ADVERTISE. For older versions, we use legacy BLUETOOTH and BLUETOOTH_ADMIN permissions with maxSdkVersion=30.

---

Q9. How do you handle BLE disconnect?

Answer:

> I listen to connection state changes in BluetoothGattCallback. On disconnect, I update UI state, close the GATT object, and retry only if required using controlled backoff.

---

Q10. How would you design BLE in Clean Architecture?

Answer:

> I keep Android BLE APIs in the data layer. The domain layer contains repository interfaces and use cases. The ViewModel exposes state using StateFlow. This keeps the UI clean and makes the BLE logic testable.

---

20. Final Revision Diagram

Bluetooth
   |
   +-- Classic
   |      |
   |      +-- Pair
   |      +-- Socket
   |      +-- Stream
   |      +-- Printer / Scanner / Speaker
   |
   +-- BLE
          |
          +-- Scan
          +-- Connect
          +-- GATT
          +-- Service
          +-- Characteristic
          +-- Notification
          +-- Watch / Sensor / Beacon

---

21. Final Interview Pitch

> Bluetooth Classic is useful for continuous communication with devices like printers, scanners, and speakers. BLE is useful for low-power communication with wearables, sensors, beacons, and IoT devices. In BLE, Android usually acts as a central device. It scans for peripherals, connects using GATT, discovers services, and reads or writes characteristics. I also handle Android 12+ permissions, stop scans after timeout, manage disconnects, and close GATT properly to avoid resource leaks.

---

22. One-Line Memory

Classic = Socket + Stream
BLE     = Scan + GATT + Service + Characteristic