Android经典蓝牙

Posted 一杯清泉

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android经典蓝牙相关的知识,希望对你有一定的参考价值。

        最近一直在做手机硬件相关的东西的,接触到了手机蓝牙,这篇文章主要介绍经典蓝牙相关的东西,下篇文章将介绍低功耗蓝牙BLE相关的东西,由于时间的关系,只是一个大概的总结和记录,相关要点在注释里面。

一、常用的蓝牙操作

1、打开蓝牙

public static void openBluetooth() {
    BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
    if (!bluetoothAdapter.isEnabled()) {
        bluetoothAdapter.enable();
    }
}

public static void openBluetooth(Activity a) {
    final BluetoothManager bluetoothManager =
            (BluetoothManager) a.getSystemService(Context.BLUETOOTH_SERVICE);
    BluetoothAdapter bluetoothAdapter = bluetoothManager.getAdapter();
    if (bluetoothAdapter != null || !bluetoothAdapter.isEnabled()) {
        Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
        a.startActivityForResult(enableBtIntent, BLUETOOTH_CODE);
    }
}

2、关闭蓝牙

public static void closeBluetooth() {
    BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
    if (bluetoothAdapter.isEnabled()) {
        bluetoothAdapter.disable();
    }
}

3、判断蓝牙是否打开

public static void openBluetooth() {
    BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
    if (!bluetoothAdapter.isEnabled()) {
        bluetoothAdapter.enable();
}

4、获取已经配对的蓝牙信息

public void getConnectedBluetoothDevices(JsGetConnectedBluetoothBean bean) {
    BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
    Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
    JsCreateDevicesBean jsCreateDevicesBean = new JsCreateDevicesBean();
    if (pairedDevices.size() > 0) {
        for (BluetoothDevice device : pairedDevices) {
            LogUtils.d("BlueTooth已配对的设备:" + device.getAddress() + "----" + device.getName());
        }
    }
}

二、蓝牙权限

1、申请权限

静态注册:

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

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> 

动态申请定位权限:

String[] p = new String[]{Manifest.permission.ACCESS_FINE_LOCATION};
ActivityCompat.requestPermissions(activity,p,1000);

        如果您的目标是 Android 10,那么您需要 ACCESS_FINE_LOCATION 来扫描。ACCESS_COARSE_LOCATION 在 Android 10 中不再起作用。

2、打开手机定位

Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
MainActivity a = (MainActivity) activity;
a.startActivityForResult(intent, OPEN_GPS_CODE)

注意:蓝牙的搜索、配对等等需要开启权限,否则啥也获取不到。

三、蓝牙搜索、获取蓝牙地址、信号强度、UUID等

1、注册蓝牙广播

IntentFilter filter = new IntentFilter();
filter.addAction(BluetoothDevice.ACTION_FOUND);
filter.addAction(BluetoothDevice.ACTION_UUID);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
activity.registerReceiver(bluetoothReceiver, filter);

2、开始搜索

if (bluetoothAdapter.isDiscovering()) {
    //搜索蓝牙设备
    bluetoothAdapter.cancelDiscovery();
}
bluetoothAdapter.startDiscovery();

这一步非常耗性能和时间,需要在子线程进行。

3、监听广播

    private List<BluetoothDevice> deviceList = new ArrayList<>();

    public BroadcastReceiver bluetoothReceiver = new BroadcastReceiver() {

        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            switch (action) {
                case BluetoothAdapter.ACTION_DISCOVERY_STARTED:
                    LogUtils.d("开始搜索");
                    break;
                case BluetoothDevice.ACTION_FOUND:
                    LogUtils.d("搜索中……");
                    BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                    short rssi = intent.getShortExtra(BluetoothDevice.EXTRA_RSSI, (short) 0);
                    if (!TextUtils.isEmpty(device.getName())) {
                        String str = device.getName() + "|" + device.getAddress() + "|" + rssi;
                        LogUtils.d("搜索到的蓝牙信息名称、地址、信号强度:" + str);
                        if (!deviceList.contains(device)) {
                            //过滤掉没有名称的重复的内容
                            deviceList.add(device);
                        }
                    }
                    break;
                case BluetoothAdapter.ACTION_DISCOVERY_FINISHED:
                    LogUtils.d("搜索结束");
                    for (int i = 0; i < deviceList.size(); i++) {
                        BluetoothDevice bluetoothDevice = deviceList.get(i);
                        //这块触发了BluetoothDevice.ACTION_UUID,以便于获取到UUID
                        bluetoothDevice.fetchUuidsWithSdp();
                        LogUtils.d(bluetoothDevice.getName() + " | " + bluetoothDevice.getAddress());
                    }
                    break;
                case BluetoothDevice.ACTION_UUID:
                    LogUtils.d("触发UUID");
                    BluetoothDevice bluetoothDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                    Parcelable[] uuid = intent.getParcelableArrayExtra(BluetoothDevice.EXTRA_UUID);
                    try {
                        //反射获取本地名称
                        Method method = bluetoothDevice.getClass().getMethod("getAlias");
                        if (method != null) {
                            String localName = (String) method.invoke(bluetoothDevice);
                        }
                    } catch (NoSuchMethodException e) {
                        e.printStackTrace();
                    } catch (InvocationTargetException e) {
                        e.printStackTrace();
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                    if (uuid != null) {
                        for (Parcelable ep : uuid) {
                            LogUtils.d("UUID :" + ep.toString());
                        }
                    } else {
                        LogUtils.d("UUID : null");
                    }
                    break;
            }
        }
    };

4、停止搜索

if (bluetoothAdapter.isDiscovering()) {
    bluetoothAdapter.cancelDiscovery();
}
activity.unregisterReceiver(bluetoothReceiver);

注意:搜索结束之后需要停止搜索,否则非常耗电,还浪费性能。

三、蓝牙自动配对

1、获取需要配对的蓝牙设备和pin码

String deviceId = data.deviceId;
String pin = data.pin;

deviceId:需要配对的设备。

pin:设置的配对码。

2、开始配对

BluetoothAdapter bluetoothAdapter = bluetoothManager.getAdapter();
BluetoothDevice remoteDevice = bluetoothAdapter.getRemoteDevice(deviceId);
if (remoteDevice.getBondState() == BluetoothDevice.BOND_BONDED) {
    //已经配对了
    LogUtils.d("已经配对了");
} else {
    //没有配对
    //监听配对状态
    IntentFilter intentFilter = new IntentFilter();
    intentFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED); //配对状态监听
    intentFilter.addAction(BluetoothDevice.ACTION_PAIRING_REQUEST);  //配对请求
    makeBluetoothPairReceiver = new MakeBluetoothPairReceiver();
    activity.registerReceiver(makeBluetoothPairReceiver, intentFilter);
    //开始配对
    remoteDevice.setPin(pinByte);
    remoteDevice.createBond();
}
    
public class MakeBluetoothPairReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (TextUtils.equals(action, BluetoothDevice.ACTION_BOND_STATE_CHANGED)) {
            BluetoothDevice bluetoothDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
            int bondSate = bluetoothDevice.getBondState();
            switch (bondSate) {
                case BluetoothDevice.BOND_NONE:
                    LogUtils.d("已解除配对");
                    unMakeBluetoothPairReceiver();
                    break;
                case BluetoothDevice.BOND_BONDING:
                    LogUtils.d("正在配对...");
                    break;
                case BluetoothDevice.BOND_BONDED:
                    LogUtils.d("配对成功");
                    unMakeBluetoothPairReceiver();
                    break;
            }
        } else if (TextUtils.equals(action, BluetoothDevice.ACTION_PAIRING_REQUEST)) {
            int type = intent.getIntExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT, BluetoothDevice.ERROR);
            LogUtils.d("ACTION_PAIRING_REQUEST:" + type);
            //  abortBroadcast();该方法使配对失败,先不用了
        }
    }
}

public void unMakeBluetoothPairReceiver() {
    if (makeBluetoothPairReceiver != null) {
        activity.unregisterReceiver(makeBluetoothPairReceiver);
    }
}

四、获取已经连接的蓝牙信息

BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
JsCreateDevicesBean jsCreateDevicesBean = new JsCreateDevicesBean();
if (pairedDevices.size() > 0) {
    List<JsCreateDevicesBean.DeviceData> list = jsCreateDevicesBean.devices;
    for (BluetoothDevice device : pairedDevices) {
        JsCreateDevicesBean.DeviceData deviceData = new JsCreateDevicesBean.DeviceData();
        deviceData.deviceId = device.getAddress();
        deviceData.name = device.getName();
        LogUtils.d("BlueTooth已配对的设备:" + device.getAddress() + "----" + device.getName() + "----" + device.getUuids().toString());
    }
}

以上是关于Android经典蓝牙的主要内容,如果未能解决你的问题,请参考以下文章

android开发SPP经典蓝牙

Windows 10连接到蓝牙经典设备而不进行配对

Android 经典蓝牙开发(一)

Android蓝牙开发(二)经典蓝牙消息传输实现

Android经典蓝牙

Android蓝牙开发—— 经典蓝牙连接方法