Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Android

Kiểm tra thiết bị Bluetooth đã kết nối trên Android

Giới thiệu

Bài viết này hướng dẫn cách kiểm tra trạng thái kết nối Bluetooth (đã cắm/đã ngắt) trên Android bằng BroadcastReceiver lắng nghe các action: ACTION_ACL_CONNECTED, ACTION_ACL_DISCONNECTED, ACTION_ACL_DISCONNECT_REQUESTED.

Các bước thực hiện

Bước 1: Tạo dự án mới

Mở Android Studio, chọn File → New Project và điền thông tin cần thiết.

Bước 2: Thiết kế giao diện (res/layout/activity_main.xml)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="16dp"
    android:gravity="center">

    <TextView
        android:id="@+id/tvStatus"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Đang kiểm tra Bluetooth..."
        android:textSize="18sp"
        android:textStyle="bold" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:text="Mở cài đặt Bluetooth và kết nối/ngắt thiết bị để test"
        android:textSize="14sp"
        android:gravity="center" />

</LinearLayout>

Bước 3: Viết code kiểm tra (src/MainActivity.java)

import androidx.appcompat.app.AppCompatActivity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    private TextView tvStatus;
    private BluetoothAdapter bluetoothAdapter;
    private BroadcastReceiver bluetoothReceiver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        tvStatus = findViewById(R.id.tvStatus);
        bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

        if (bluetoothAdapter == null) {
            tvStatus.setText("Thiết bị không hỗ trợ Bluetooth");
            return;
        }

        // Kiểm tra trạng thái hiện tại
        updateStatus(bluetoothAdapter.isEnabled() ? "Bluetooth: BẬT" : "Bluetooth: TẮT");

        // BroadcastReceiver cho trạng thái kết nối thiết bị
        bluetoothReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                String action = intent.getAction();
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                String deviceName = device != null ? device.getName() : "Unknown";

                if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)) {
                    String msg = "Đã kết nối: " + deviceName;
                    updateStatus(msg);
                    Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();
                } else if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action)) {
                    String msg = "Đã ngắt kết nối: " + deviceName;
                    updateStatus(msg);
                    Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();
                } else if (BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED.equals(action)) {
                    // Đang trong quá trình ngắt kết nối
                    updateStatus("Đang ngắt kết nối: " + deviceName);
                }
            }
        };

        // Đăng ký receiver
        IntentFilter filter = new IntentFilter();
        filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
        filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
        filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED);
        // Thêm cả state change của adapter
        filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
        registerReceiver(bluetoothReceiver, filter);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (bluetoothReceiver != null) {
            unregisterReceiver(bluetoothReceiver);
        }
    }

    private void updateStatus(String message) {
        runOnUiThread(() -> tvStatus.setText(message));
    }
}

Bước 4: Manifest (androidManifest.xml)

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="https://schemas.android.com/apk/res/android"
    package="app.com.sample">

    <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
    
    <!-- Android 12+ (API 31+) -->
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
    <uses-permission android:name="android.permission.BLUETOOTH_SCAN" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <activity android:name=".MainActivity">
            <intent-filter>
                
                
            </intent-filter>
        </activity>

    </application>
</manifest>

Chạy ứng dụng

Kết nối thiết bị thật (emulator không hỗ trợ Bluetooth thật), nhấn Run. Bật Bluetooth, kết nối tai nghe/loa -> thấy Toast "Đã kết nối". Ngắt kết nối -> thấy "Đã ngắt kết nối".

Quyền Bluetooth theo phiên bản Android

Android Version API Level Permissions Required
Android 11 và cũ hơn ≤ 30 BLUETOOTH, BLUETOOTH_ADMIN
Android 12 (S) 31 BLUETOOTH_CONNECT, BLUETOOTH_SCAN (runtime)
Android 13+ (T+) 33+ BLUETOOTH_CONNECT, BLUETOOTH_SCAN + BLUETOOTH_ADVERTISE nếu cần

Runtime Permission (Android 12+)

// Kiểm tra và yêu cầu quyền runtime
private void checkBluetoothPermissions() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
        String[] permissions = {
            Manifest.permission.BLUETOOTH_CONNECT,
            Manifest.permission.BLUETOOTH_SCAN
        };
        for (String perm : permissions) {
            if (checkSelfPermission(perm) != PackageManager.PERMISSION_GRANTED) {
                requestPermissions(permissions, REQUEST_CODE_BLUETOOTH);
                return;
            }
        }
    }
    // Permission granted, proceed
    initBluetooth();
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == REQUEST_CODE_BLUETOOTH) {
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            initBluetooth();
        }
    }
}

Lấy danh sách thiết bị đã ghép đôi (Bonded)

// Lấy tất cả thiết bị đã paired
Set bondedDevices = bluetoothAdapter.getBondedDevices();
for (BluetoothDevice device : bondedDevices) {
    String name = device.getName();
    String address = device.getAddress(); // MAC address
    int bondState = device.getBondState(); // BOND_BONDED, BOND_BONDING, BOND_NONE
    
    // Kiểm tra kết nối hiện tại (cần connect socket hoặc dùng BroadcastReceiver như trên)
}

Kiểm tra kết nối Profile cụ thể (A2DP, HFP, HID...)

// Cần BLUETOOTH_PRIVILEGED (system app) hoặc dùng Reflection
// Hoặc dùng BluetoothProfile.ServiceListener (API 11+)
bluetoothAdapter.getProfileProxy(this, new BluetoothProfile.ServiceListener() {
    @Override
    public void onServiceConnected(int profile, BluetoothProfile proxy) {
        if (profile == BluetoothProfile.A2DP) {
            // Kiểm tra thiết bị đang kết nối A2DP (audio streaming)
            for (BluetoothDevice device : proxy.getConnectedDevices()) {
                // device đang phát nhạc
            }
        }
    }
    @Override
    public void onServiceDisconnected(int profile) {}
}, BluetoothProfile.A2DP);

Lưu ý quan trọng

  • BroadcastReceiver chỉ nhận khi app chạy (foreground). Muốn nhận khi app background/killed: dùng BluetoothAdapter.setBluetoothPolicy() hoặc CompanionDeviceManager.
  • Không thể liệt kê thiết bị đang kết nối trực tiếp từ BluetoothAdapter public API (cần reflection hoặc Profile Proxy).
  • Luôn unregisterReceiver trong onDestroy.
  • Test trên thiết bị thật - emulator không có Bluetooth hardware.