• BlueTooth


    本文主要介绍,蓝牙开启、蓝牙扫描、配对,建立链接,进行通信。

    1.声明权限:

    1. <uses-permission android:name="android.permission.INTERNET" />
    2. <uses-permission android:name="android.permission.BLUETOOTH" />
    3. <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
    4. <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    5. <uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
    6. <uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
    7. <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

    2.获取蓝牙适配器:

    1. // 获取蓝牙配置器 BluetoothAdapter 方式1.
    2. BluetoothManager bluetoothManger =
    3. (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
    4. bluetoothAdapter = bluetoothManger.getAdapter();
    5. //方式2
    6. // bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

    3.开启蓝牙:

    1. if (!bluetoothAdapter.isEnabled()) {
    2. // 没有开启蓝牙 开启蓝牙
    3. Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
    4. startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
    5. }

     

    4.动态申请权限:

    1. //判断是否有访问位置的权限,没有权限,直接申请位置权限
    2. if ((checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED)
    3. || (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED)) {
    4. requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION}, 200);
    5. }

    5.创建蓝牙结果列表,并添加点击事件。

    1. // 创建设备列表适配器
    2. deviceListAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1);
    3. deviceListView = (ListView) findViewById(R.id.device_list);
    4. deviceListView.setAdapter(deviceListAdapter);
    5. deviceListView.setOnItemClickListener((adapterView, view, i, l) -> {
    6. if (bluetoothAdapter.isDiscovering()) {
    7. bluetoothAdapter.cancelDiscovery();
    8. }
    9. String deviceName = deviceListAdapter.getItem(i);
    10. Log.e("nyz", "deviceName " + deviceName);
    11. selectedDevice = bluetoothAdapter.getRemoteDevice(deviceName.split("\\n")[1]);
    12. Log.e("nyz", "name " + selectedDevice.getName());
    13. Log.e("nyz", "address " + selectedDevice.getAddress());
    14. ParcelUuid[] uuids = selectedDevice.getUuids();
    15. for (int index = 0; index < uuids.length; index++) {
    16. Log.e("nyz", "uuids " + uuids[index]);
    17. }
    18. connectToDevice(selectedDevice);
    19. });

    6.创建广播接受者,用于接收扫描到蓝牙后的结果。

       

    1. @SuppressLint("MissingPermission")
    2. private final BroadcastReceiver deviceReceiver = new BroadcastReceiver() {
    3. @Override
    4. public void onReceive(Context context, Intent intent) {
    5. String action = intent.getAction();
    6. Log.e("nyz", "action " + action);
    7. // 当有新设备被发现时
    8. if (BluetoothDevice.ACTION_FOUND.equals(action)) {
    9. BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
    10. deviceListAdapter.notifyDataSetChanged();
    11. if (!TextUtils.isEmpty(device.getName())) {
    12. deviceListAdapter.add(device.getName() + "\n" + device.getAddress());
    13. }
    14. }
    15. // 做配对使用
    16. else if (BluetoothDevice.ACTION_PAIRING_REQUEST.equals(action)) {
    17. BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
    18. int pairingVariant = intent.getIntExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT, BluetoothDevice.ERROR);
    19. // 如果需要 PIN 码,可以在这里自动输入
    20. if (pairingVariant == BluetoothDevice.PAIRING_VARIANT_PIN) {
    21. device.setPin("1234".getBytes()); // 替换为您的 PIN 码
    22. }
    23. // 如果需要用户确认配对请求,可以在这里显示对话框来请求用户确认
    24. } else if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)) {
    25. BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
    26. int bondState = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.ERROR);
    27. int previousBondState = intent.getIntExtra(BluetoothDevice.EXTRA_PREVIOUS_BOND_STATE, BluetoothDevice.ERROR);
    28. // 配对状态改变的处理逻辑
    29. if (bondState == BluetoothDevice.BOND_BONDED && previousBondState == BluetoothDevice.BOND_BONDING) {
    30. // 配对成功
    31. } else if (bondState == BluetoothDevice.BOND_NONE && previousBondState == BluetoothDevice.BOND_BONDED) {
    32. // 配对解除
    33. }
    34. } else if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)) {
    35. Log.e("nyz", "搜索开始..");
    36. } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
    37. Log.e("nyz", "搜索结束..");
    38. } else if (BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED.equals(action)) {
    39. int state = intent.getIntExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE, BluetoothAdapter.ERROR);
    40. if (state == BluetoothAdapter.STATE_CONNECTING) {
    41. Log.e("nyz", "正在链接...");
    42. } else if (state == BluetoothAdapter.STATE_CONNECTED) {
    43. // Log.e("nyz", "链接成功...");
    44. // InputStream inputStream = null;
    45. // try {
    46. // inputStream = bluetoothSocket.getInputStream();
    47. // OutputStream outputStream = bluetoothSocket.getOutputStream();
    48. // Log.e("nyz", "inputStream " + (inputStream != null));
    49. // Log.e("nyz", "outputStream " + (outputStream != null));
    50. // Log.e("nyz", "获取流成功..");
    51. // } catch (IOException e) {
    52. // e.printStackTrace();
    53. // }
    54. } else if (state == BluetoothAdapter.STATE_DISCONNECTED) {
    55. Log.e("nyz", "断开链接...");
    56. }
    57. }
    58. }
    59. };

    7.注册和反注册:

      

    1. // 注册广播
    2. public void registerBroadcast() {
    3. // 注册广播接收器
    4. IntentFilter intent = new IntentFilter();
    5. intent.addAction(BluetoothDevice.ACTION_FOUND);//搜索发现设备
    6. intent.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);//状态改变
    7. intent.addAction(BluetoothDevice.ACTION_PAIRING_REQUEST);//配对请求
    8. intent.addAction(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);//行动扫描模式改变了
    9. intent.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);//动作状态发生了变化
    10. intent.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);//搜索结束
    11. intent.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);//开始搜索
    12. intent.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);//链接状态变化
    13. registerReceiver(deviceReceiver, intent);
    14. }
    15. @Override
    16. protected void onDestroy() {
    17. super.onDestroy();
    18. // 取消注册广播接收器
    19. unregisterReceiver(deviceReceiver);
    20. }

    8.开始搜索附近蓝牙设备:

         bluetoothAdapter.startDiscovery,搜索结束后,会通过广播的形式来接收。

    bluetoothAdapter.getBondedDevices() 返回的是已经配对过的蓝牙设备列表。  

    1. private void startDeviceDiscovery() {
    2. deviceListAdapter.clear();
    3. int state = bluetoothAdapter.getState();
    4. Log.e("nyz", "state " + state);
    5. boolean b = bluetoothAdapter.startDiscovery();
    6. Log.e("nyz", "bluetooth state " + b);
    7. //获取已经连接过的设备。
    8. Set<BluetoothDevice> bondedDevices = bluetoothAdapter.getBondedDevices();
    9. for (BluetoothDevice device : bondedDevices) {
    10. Log.e("nyz", "device " + device.getName());
    11. deviceListAdapter.add(device.getName() + "\n" + device.getAddress());
    12. deviceListAdapter.notifyDataSetChanged();
    13. }
    14. }

    9.附近蓝牙设备结果:添加到列表中。

    1. // 当有新设备被发现时
    2. if (BluetoothDevice.ACTION_FOUND.equals(action)) {
    3. BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
    4. deviceListAdapter.notifyDataSetChanged();
    5. if (!TextUtils.isEmpty(device.getName())) {
    6. deviceListAdapter.add(device.getName() + "\n" + device.getAddress());
    7. }
    8. }

    10.点击列表中的蓝牙进行配对链接,没有配对过的需要配对,已经配对过的,可以直接链接。

          1)点击事件

    1. deviceListView.setOnItemClickListener((adapterView, view, i, l) -> {
    2. //当点击某个蓝牙列表时,需要停止扫描,减少性能的消耗
    3. if (bluetoothAdapter.isDiscovering()) {
    4. bluetoothAdapter.cancelDiscovery();
    5. }
    6. String deviceName = deviceListAdapter.getItem(i);
    7. Log.e("nyz", "deviceName " + deviceName);
    8. selectedDevice = bluetoothAdapter.getRemoteDevice(deviceName.split("\\n")[1]);
    9. Log.e("nyz", "name " + selectedDevice.getName());
    10. Log.e("nyz", "address " + selectedDevice.getAddress());
    11. ParcelUuid[] uuids = selectedDevice.getUuids();
    12. for (int index = 0; index < uuids.length; index++) {
    13. Log.e("nyz", "uuids " + uuids[index]);
    14. }
    15. //开始链接
    16. connectToDevice(selectedDevice);
    17. });

       2)开始配对链接:

         需要放在子线程中执行。

    1. @SuppressLint("MissingPermission")
    2. private void connectToDevice(BluetoothDevice device) {
    3. new Thread() {
    4. @Override
    5. public void run() {
    6. super.run();
    7. UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); // SPP UUID for serial communication
    8. try {
    9. // 进行配对
    10. if (!(device.getBondState() == BluetoothDevice.BOND_BONDED)) {
    11. Log.e("nyz", "等待配对");
    12. boolean success = device.createBond();
    13. Log.e("nyz", "配对结果 " + success);
    14. } else {
    15. Log.e("nyz", "已经配对过");
    16. }
    17. // 等待配对完成
    18. // Thread.sleep(500);
    19. Log.e("nyz", "创建 socket");
    20. bluetoothSocket = device.createRfcommSocketToServiceRecord(uuid);
    21. Log.e("nyz", "connect...");
    22. if (bluetoothSocket == null) {
    23. Log.e("nyz", "connect...failed");
    24. return;
    25. } else {
    26. Log.e("nyz", "socket 创建成功");
    27. }
    28. new Thread() {
    29. @Override
    30. public void run() {
    31. super.run();
    32. try {
    33. bluetoothSocket.connect();
    34. // 成功连接
    35. Log.e("nyz", "链接成功...");
    36. InputStream inputStream = bluetoothSocket.getInputStream();
    37. OutputStream outputStream = bluetoothSocket.getOutputStream();
    38. Log.e("nyz", "inputStream " + (inputStream != null));
    39. Log.e("nyz", "outputStream " + (outputStream != null));
    40. } catch (Exception e) {
    41. e.printStackTrace();
    42. }
    43. }
    44. }.start();
    45. } catch (Exception e) {
    46. Log.e("nyz", "conn failed");
    47. e.printStackTrace();
    48. }
    49. }
    50. }.start();
    51. }

     配对成功后, bluetoothSocket = device.createRfcommSocketToServiceRecord(uuid);

    拿到一个一个Socket对象。

    开始链接:

    1. bluetoothSocket.connect();
    2. // 成功连接
    3. Log.e("nyz", "链接成功...");
    4. InputStream inputStream = bluetoothSocket.getInputStream();
    5. OutputStream outputStream = bluetoothSocket.getOutputStream();
    6. Log.e("nyz", "inputStream " + (inputStream != null));
    7. Log.e("nyz", "outputStream " + (outputStream != null));

    链接成功后,可以从socket中拿到输入输出流,这样就可以和另外一台设计进行通信了。

    和串口类似,串口通信,也是拿到一个输入输出流。

    蓝牙通信官方文档:

    蓝牙概览  |  Connectivity  |  Android Developers

  • 相关阅读:
    第二十章 运动函数的封装
    基于Python的农业统计数据可视化系统设计与实现
    在虚拟机Linux上写c语言代码
    Hbase
    30个有发展前景的创业项目
    计算机毕业设计ssm电商后台管理系统tgm41系统+程序+源码+lw+远程部署
    Opensuse Tumbleweed快速部署K8S-1.28.2
    js 实现删除数组指定元素
    uniapp接入萤石微信小程序插件
    Kafka常用参数
  • 原文地址:https://blog.csdn.net/niuyongzhi/article/details/133773269