+2

Android Bluetooth Classic - Part 2

Tiếp tục trong chuỗi bài liên quan đến Bluetooth Classic trong Android. Mình xin chia sẻ phần liên quan đến Tìm kiếm (Scanning - Discovery) và Enable discoverability thiết bị.

1. Tìm kiếm (Scanning - Discovery) thiết bị Bluetooth

Để bắt đầu tìm kiếm (Scanning) thiết bị, hàm startDiscovery() thông qua đối tượng BluetoothAdapter được gọi. Quá trình này bất đồng bộ (asynchronous) và trả về một giá trị boolean cho biết quá trình discovery đã bắt đầu thành công hay chưa. Theo như mình tìm hiểu thì quá trình scan thường được truy vấn trong khoảng 12 giây, sau đó hiển thị output lên màn hình hoặc nơi hiển thị kết quả.

Để nhận thông tin về từng thiết bị được quét (tìm thấy) thành công, ứng dụng của bạn phải register một BroadcastReceiver với ACTION_FOUND intent. Hệ thống sẽ broadcasts intent này cho từng thiết bị. Trong intent này sẽ chứa công tin về device thông qua các extra fields như EXTRA_DEVICE và EXTRA_CLASS.

Cụ thể:

class LegacyPairingFlowBluetoothDeviceReceiver(
    private val mListener: Listener
) : BroadcastReceiver() {

    companion object {
        private const val RESTART_DISCOVERY_DELAY = 5_000L // ms
    }

    private val handler = Handler(Looper.getMainLooper())
    private val restartDiscovery = Runnable {
        if (!cancelScan) {
            BluetoothAdapter.getDefaultAdapter()?.startDiscovery()
        }
    }

    var cancelScan: Boolean = false
        set(value) {
            field = value
            if (value) {
                handler.removeCallbacks(restartDiscovery)
            }
        }

    override fun onReceive(context: Context, intent: Intent) {
        val state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR)
        if (state == BluetoothAdapter.STATE_ON && !cancelScan) {
            BluetoothAdapter.getDefaultAdapter()?.startDiscovery()
        }

        val action = intent.action
        if (BluetoothDevice.ACTION_FOUND == action) {
            val device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE) as? BluetoothDevice
            if (device != null) {
                mListener.onFoundBluetoothDevice(device)
            }
        } else if (BluetoothAdapter.ACTION_DISCOVERY_STARTED == action) {
            mListener.onDiscoveryStarted()
        } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED == action) {
            if (!cancelScan) {
                handler.postDelayed(restartDiscovery, RESTART_DISCOVERY_DELAY)
            }
            mListener.onDiscoveryFinished()
        }

        if (BluetoothAdapter.STATE_ON == state) {
            mListener.onBluetoothStateOn()
        }
    }

    interface Listener {
        fun onFoundBluetoothDevice(device: BluetoothDevice)

        fun onDiscoveryStarted()

        fun onDiscoveryFinished()

        fun onBluetoothStateOn() {}
    }
}

Để bắt đầu kết nối với thiết bị Bluetooth, bạn gọi getAddress() của BluetoothDevice để truy xuất địa chỉ MAC được liên kết.

Note: Thực hiện tìm kiếm (gọi discovery) thiết bị tiêu tốn rất nhiều tài nguyên. Sau khi bạn đã tìm thấy một thiết bị để kết nối, hãy chắc chắn rằng bạn dừng việc tìm kiếm lại bằng function cancelDiscovery() trước khi thử connect với thiết bị đó. Ngoài ra, bạn không nên thực hiện tìm kiếm (gọi discovery) khi được kết nối với thiết bị vì quá trình tìm kiếm làm giảm đáng kể băng thông khả dụng cho bất kỳ kết nối hiện có.

2. Enable discoverability

Nếu bạn chỉ cần kết nối từ ứng dụng của bạn với một thiết bị Bluetooth, transfer data với chúng thì bạn không cần phải Enable discoverability của thiết bị. Enable discoverability chỉ cần thiết khi bạn muốn ứng dụng của mình là một host a server socket chấp nhận các kết nối đến, vì các thiết bị Bluetooth phải có thể khám phá các thiết bị khác trước khi khởi động kết nối với các thiết bị khác.

Để thực hiện điều đó, chúng ta gọi hàm startActivityForResult(Intent, int) với action Intent tương ứng là ACTION_REQUEST_DISCOVERABLE. Theo mặc định, thiết bị có thể được discover trong hai phút. Bạn có thể xác định thời lượng khác, tối đa một giờ, bằng cách thêm EXTRA_DISCOVERABLE_DURATION extra cho Intent đó.

    val requestCode = 1;
    val discoverableIntent: Intent = Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE).apply {
       putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 500)
    }
    startActivityForResult(discoverableIntent, requestCode)

Note: Nếu Bluetooth chưa được bật trên thiết bị, thì việc Enable discoverability sẽ tự động bật Bluetooth.

Bài tiếp theo mình sẽ trình bày về việc Connect và Transfer giữa ứng dụng và thiết bị Bluetooth.


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí