zoukankan      html  css  js  c++  java
  • Android 读取蓝牙设备信息开发

    (1)Android手机一般以客户端的角色主动连接SPP协议设备(接上蓝牙模块的数字传感器),连接流程是:
      1.使用registerReceiver注册BroadcastReceiver来获取蓝牙状态、搜索设备等消息;
      2.使用BlueAdatper的搜索;
      3.在BroadcastReceiver的onReceive()里取得搜索所得的蓝牙设备信息(如名称,MAC,RSSI);
      4.通过设备的MAC地址来建立一个BluetoothDevice对象;

      5.由BluetoothDevice衍生出BluetoothSocket,准备SOCKET来读写设备;

      6.通过BluetoothSocket的createRfcommSocketToServiceRecord()方法来选择连接的协议/服务,这里用的是SPP(UUID:00001101-0000-1000-8000-00805F9B34FB);
      7.Connect之后(如果还没配对则系统自动提示),使用BluetoothSocket的getInputStream()和getOutputStream()来读写蓝牙设备。

    ****************注意:对于UUID,必须使用Android的SSP(协议栈默认)的UUID:00001101-0000-1000-8000-00805F9B34FB才能正常和外部的,也是SSP串口的蓝牙设备去连接。

    (2)添加权限

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

    (3)BluetoothAdapter类:

    BluetoothAdapter类简单点来说就是代表了本设备(手机、电脑等)的蓝牙适配器对象,通过它我们可以蓝牙设备进行基本开发了。

    主要有如下功能:

      1、开关蓝牙设备

      2、扫描蓝牙设备

      3、设置/获取蓝牙状态信息,例如:蓝牙状态值、蓝牙Name、蓝牙Mac地址等;

    BluetoothAdapter初始化并提示打开蓝牙使用:

     1 private BluetoothAdapter  mBluetoothAdapter;
     2 mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
     3 if (!mBluetoothAdapter.isEnabled()) {
     4     //弹出对话框提示用户是后打开
     5     Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
     6     startActivity(intent);
     7     //  startActivityForResult(intent, REQUEST_ENABLE);
     8     //不做提示,强行打开
     9     // mBluetoothAdapter.enable();
    10 }

    创建监听蓝牙状态的广播:

     1 BroadcastReceiver mFoundReceiver = new BroadcastReceiver() {
     2 
     3         public void onReceive(Context context, Intent intent) {
     4             String action = intent.getAction();
     5             //找到设备
     6             if (BluetoothDevice.ACTION_FOUND.equals(action)) {
     7                 BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
     8                 // 添加进一个设备列表,进行显示。
    12                 if (device.getBondState() != BluetoothDevice.BOND_BONDED) {
    13                     Log.v(TAG, "find device:" + device.getName() + device.getAddress());
    14                 }
    15             }
    16             //搜索完成
    17             else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
    18                 cancelDiscovery();20             }
    21         }
    22     };

    注册广播监听蓝牙状态:

     1 private void startDiscovery() { 5     IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);//开启搜索
     6     registerReceiver(mFoundReceiver, filter);
     7     filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);//搜索完成
     8     registerReceiver(mFoundReceiver, filter);15     mBluetoothAdapter.startDiscovery();17 }

    开启和关闭蓝牙扫描:

    // 开启
    mBluetoothAdapter.startDiscovery();
    // 关闭
    mBluetoothAdapter.cancelDiscovery();

    点击扫描到的列表,传递点击项的BluetoothDevice通过putExtra给蓝牙数据显示界面。

    4)进行BluetoothSocket socket 和 BluetoothDevice mBluetoothDevice 进行操作。

     1 private class ConnectThread extends Thread {
     2 
     3         public ConnectThread(BluetoothDevice device) {
     4             try {
     5                 socket = device.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
     6             } catch (IOException e) {
     7                 e.printStackTrace();
     8             }
    10         }
    11 
    12         public void run() {
    13             while (mAutoConnectInterruptTime < 5) {
    14                 try {
    15 
    16                     socket.connect();
    17                     runOnUiThread(new Runnable() {
    18                         @Override
    19                         public void run() {
    20                             // TODO 显示连接成功
    21                         }
    22                     });
    23                     isConnect = true;
    24                     mAutoConnectInterruptTime = 0;
    25                     manageConnectedSocket(socket); // 创建新的线程对蓝牙进行数据读取。
    26                     break;
    27 
    28                 } catch (Exception e) {
    29                     e.printStackTrace();
    30                     mAutoConnectInterruptTime++;
    31 
    32                     try {
    33                         Thread.sleep(2000);
    34                     } catch (InterruptedException e1) {
    35                         e1.printStackTrace();
    36                     }
    37 
    38                     runOnUiThread(new Runnable() {
    39                         @Override
    40                         public void run() {
    41                             // TODO 显示连接失败
    42                         }
    43                     });
    44                     // TODO 进行对 inputStream outputStream socket 进行关闭 置空.
    45                     return;
    46                 }
    47             }
    48 
    49         }
    50 
    51         public void cancel() {
    52             try {
    53                 socket.close();
    54             } catch (IOException e) {
    55                 e.printStackTrace();
    56             }
    57         }
    58     }

    (5)通过BluetoothSocket socket 蓝牙数据读取:

     1 public class Receive extends Thread {
     2         // 变量 略过
     3 
     4         // 构造方法
     5         public Receive(BluetoothSocket socket) {
     6 
     7             // 获取输入流
     8             try {
     9                 inputStream = socket.getInputStream();
    10                 outputStream = socket.getOutputStream();
    11             } catch (IOException e) {
    12                 e.printStackTrace();
    13             }
    14         }
    15 
    16         @Override
    17         public void run() {
    18             final byte[] bytes = new byte[1024];// 缓冲数据流
    19             int          count;// 返回读取到的数据
    20             // 监听输入流
    21             try {
    22                 while (inputStream != null && (count = inputStream.read(bytes)) != -1) {
    23                     //获取有效部分
    24                     final byte[] contents = new byte[count];
    25                     for (int i = 0; i < contents.length; i++) {
    26                         contents[i] = bytes[i];
    27                     }
    28                     parse(contents); // TODO 对读取到数据进行转换
    29                 }
    30             } catch (Exception e) {
    31                 e.printStackTrace();
    32             }
    33 
    34             ConnectThread connectBtThread = new ConnectThread(mBluetoothDevice);
    35             connectBtThread.start();
    36             // TODO 进行对 inputStream outputStream socket 进行关闭 置空。
    37             runOnUiThread(new Runnable() {
    38                 @Override
    39                 public void run() {
    40                     // TODO 关闭蓝牙连接
    41                 }
    42             });
    43             // TODO inputStream outputStream socket 进行关闭 置空
    44         }
    45     }

    参考:

    关于用到BluetoothServerSocket和BluetoothSocket两个类来建立Server端和Client端,还需要使用到一些关于流(Stream)的知识。

    • BluetoothServerSocket——服务端(监听端、监听器、接受请求的一端)
      • Accept()——阻塞宿主线程,直至收到客户端请求。返回BluetoothSocket对象。由于这个
      • Accept(int timeout)——阻塞宿主线程,直至收到客户端请求或等待时间超过timeout。返回BluetoothSocket对象。
      • Close()——关闭BluetoothServerSocket监听器。

      可以看到,Accept方法是一个阻塞方法,所以在进行开发的时候,一般都需要用到多线程的知识。JAVA的多线程知识。

    • BluetoothSocket——客户端(请求端)
      • Close()——关闭BluetoothSocket请求端。
      • Connect()——主动向服务端(监听端)发起连接请求。

    可使用BluetoothAdapter类的listenUsingRfcommWithServiceRecord方法来新建一个ServerSocket。

      可以使用web上的任何一款UUID产生器为你的程序获取一个UUID,然后使用fromString(String)初始化一个UUID。

      使用ServerSocket实例的accept方法进行监听,当监听到带有我们初始化的UUID参数的连接请求后作出响应,连接成功后返回一个BluetoothSocket对象。连接完成后,调用close方法关闭该Socket监听。

    使用BluetoothDevice的实例的createRfcommSocketToServiceRecord方法来创建一个BluetoothSocket实例。

      传入我们服务端的UUID值。

      然后使用BluetoothSocket实例的Connect方法对Server端进行连接请求,当连接成功后,Client端和Server端的传输通道就被打开。

    参考链接:

    Android中连接蓝牙设备时遇到createRfcommSocketToServiceRecord的UUID问题和BluetoothSocket的connect失败

    http://www.cnblogs.com/cxcco/archive/2012/01/15/2322783.html

  • 相关阅读:
    递归函数的写法笔记
    Spring项目中执行Java脚本
    关于秒杀的系统架构优化思路
    分布式搜索引擎Elasticsearch性能优化与配置
    分布式搜索引擎ElasticSearch+Kibana (Marvel插件安装详解)
    分布式搜索引擎Elasticsearch的查询与过滤
    Linux 下编译升级 Python
    搭建通过 ssh 访问的 Git 服务器
    分布式搜索引擎Elasticsearch的简单使用
    PHP 源码学习之线程安全
  • 原文地址:https://www.cnblogs.com/CharlesGrant/p/4924169.html
Copyright © 2011-2022 走看看