Android开发之蓝牙(一)——基于SPP协议蓝牙模块通信

2023-10-29

本文意在介绍蓝牙开发的主要流程,学习使用蓝牙开发一个星期了,写写一个星期以来遇到的一些小问题,还有介绍下流程。开发具有基本的通信功能,本项目主要是用于与蓝牙模块的串口读写功能。
下一篇文章还有Android开发之蓝牙(二)——基于BLE协议蓝牙模块通信:
http://blog.csdn.net/wzhworld/article/details/76324738

使用设备

1、魅族手机
2、蓝牙FSC-BT826
3、最终目的是做出能与串口调试助手通信的功能

基本概念

1、适配器:
BuletoothAdapter:本地蓝牙的适配器,也就是说当前应用程序所运行的Android设备上的蓝牙。
BuletoothDevice : 远程的蓝牙适配器,也就是说你要连接的Android设备的适配器。。

2、权限:
android.permission.BLUETOOTH : 一些配置连接蓝牙的权限
android.permission.BLUETOOTH_ADMIN : 进行操作的权限

3、相关广播:
BluetoothDevice.ACTION_FOUND:表示可搜索到附近的蓝牙设备
BluetoothDevice.ACTION_PAIRING_REQUEST:配对请求
BluetoothAdapter.ACTION_STATE_CHANGE:配对状态改变

后面两个因为刚刚开始用的时候很迷糊,所以就直接是自动匹配,所以这两个都没怎么用到,不过感觉如果是要做这一方面的话得去了解这些广播代表什么。

基本流程

这里写图片描述

程序写得有点乱,所以还是说下大概程序写法,
(1)我是在主活动初始化布局、蓝牙适配、获取选定蓝牙设备,PS:得先匹配后才能连接
(2)然后开启一个服务,通过广播从主活动把选定蓝牙对象发送到服务中。
(3)服务收到之后主要所做的任务就是开启两个线程,一个是负责对蓝牙的socket进行连接,另一个是通过socket进行读写,第二个线程主要进行的是read,而写只需要在需要的时候才使用,所以不需要在run中。
(4)异步线程采用消息机制handler进行成功失败消息的传输。

1、检测蓝牙以及权限是否开启

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


//获取蓝牙适配器,当没有开启时开启,会回调一个成功与否的结果
private void initBluetooth() {
    if(!mBluetoothAdapter.isEnabled()){
        Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
        startActivityForResult(enableIntent, REQUEST_ENABLE);
    }
}

2、此时注册一个广播接收器进行接收

//注册广播

IntentFilter discoveryFilter = new IntentFilter();
    discoveryFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
    discoveryFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
    discoveryFilter.addAction(BluetoothDevice.ACTION_FOUND);
    discoveryFilter.addAction(BluetoothTools.ACTION_CONNECT_ERROR);
    discoveryFilter.addAction(BluetoothTools.ACTION_CONNECT_SUC);
    discoveryFilter.addAction(BluetoothTools.ACTION_RECEIVE_DATA);
    registerReceiver(mBluetoothReceiver, discoveryFilter);

3、获取本地适配器,进行连接

public BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
            ******
 if (!mBluetoothAdapter.isEnabled()) {
      mBluetoothAdapter.enable();//异步的,不会等待结果,直接返回。

     } else if(!mBluetoothAdapter.isDiscovering()) {
      mBluetoothAdapter.startDiscovery();
      } //如果设备正在寻找

4、进行匹配,连接

ClsUtils.createBond(mLastBluetoothDevice.getClass(), mLastBluetoothDevice);
ClsUtils.setPin(mLastBluetoothDevice.getClass(), mLastBluetoothDevice,pin);

使用了一个ClsUtils的工具类,其实就是将一些创建配对什么的提供一个方法,简单化。
不过遇到的奇怪的问题就是我createBond创建配对之后,使用Pin配对会自动配对,并没有说弹出窗口,查了下网上说需要取消窗口什么的,我试了也是不行,所以就最后没管了,直接一个自动配对,不过pin是死的,我设了0000,对BT826模块等蓝牙模块才有用。

5、在主活动获取对象之后,传到服务之中去开启线程。首先是开启连接的线程

 //如果匹配成功
  if (BluetoothTools.ACTION_PAIRING_SUCC.equals(actionCon)){
    Bundle mBundle = intent.getExtras();
    BluetoothDevice mBluetoothDevice = mBundle.getParcelable("Pairing_Succ");
    BluetoothClientConnThread mThread = new BluetoothClientConnThread(handler,mBluetoothDevice);
    mThread.start();//开钱连接线程
}

6、进行连接的具体过程
注意连接之前要取消扫描,因为扫描是一个很费时的动作,连接通信的过程其实与网络的SOCKET相似。

//UUID匹配
socket = serverDevice.createRfcommSocketToServiceRecord(BluetoothTools.PRIVATE_UUID);//蓝牙模块的UUID是固定(只对于spp),是00001101-0000-1000-8000-00805F9B34FB

BluetoothAdapter.getDefaultAdapter().cancelDiscovery();
socket.connect();
Log.e("Socket connect",String.valueOf(socket.isConnected()));

7、开启聊天的线程
通过广播读取editView写的数据,然后用的是gbk,当时有用过UTF8但是传输我记得发生乱码

         //如果键盘点击send发送数据            
                         if(BluetoothTools.ACTION_DATA_TO_GAME.equals(actionCon)){
try {
   String editData = (String)intent.getExtras().get("editViewData");
   byte[] bytes = editData.getBytes("gbk");
   communThread.write(bytes);
   } catch (UnsupportedEncodingException e) {
      e.printStackTrace();
   }

8、通信线程的read、write

bytes = mmInStream.read(buffer);
            serviceHandler.obtainMessage(BluetoothTools.MESSAGE_READ_OBJECT, bytes, -1, buffer).sendToTarget();

就是将读到的buffer通过消息机制传回服务,

 /* Call this from the main activity to send data to the remote device */
public void write(byte[] bytes) {
    try {
        mmOutStream.write(bytes);
    } catch (IOException e) { }
}

当时也参考了很多的文章,有得是用object传输的,但传的的时候有点问题,传不了,所以最后都改为使用字节流传输。

基本大概的spp通信就是这样一个过程,整体上不算很难,但因为属于初学阶段用起来还不是很熟练,所以学得久一点。下一篇的BLE其实大概过程相差不会很大,但有一些会改变。

Android开发之蓝牙(二)——基于BLE协议蓝牙模块通信

git下载
csdn下载

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android开发之蓝牙(一)——基于SPP协议蓝牙模块通信 的相关文章

  • 区块链技术应用学习

    学习导入 今天 以云计算 大数据 人工智能 区块链等为代表的的新一轮科技革命 对金融业 产生着前所未有的影响 新技术正义其独有的渗透性 冲击性 倍增性和创新性推动金融行 业发展到一个全新节点 金融科技人才 是复合型创新人才 需要金融方面掌握

随机推荐

  • Wrong Ramdisk Image Format Ramdisk image is corrupt or invalid

    在学习正点原子的阿尔法开发板时启动内核出错 出现 Wrong Ramdisk Image Format Ramdisk image is corrupt or invalid 报错 原因 因为我是直接复制的 因此中间 那个 格式不对 自己手
  • JavaScript和了解一切的压力,克里斯蒂安·海尔曼

    In this episode of the Versioning Show Tim and David are joined by Christian Heilmann well known developer speaker autho
  • Spring Framework---IOC/DI

    目录 1 Spring框架的主要内容 1 1Spring的发展版本 1 2Spring系统架构 1 核心层 2 AOP层 3 数据层 4 Web层 5 Test层 1 3Spring核心概念 1 3 1IOC Inversion of co
  • XSS-Labs通关(1-18)

    目录 Level1 Level2 Level3 Level4 Level5 Level6 Level7 Level8 Level9 Level10 Level11 Level12 Level13 Level15 Level16 Level1
  • Java获取文件名、文件前缀名、文件类型(文件后缀名)

    获取文件名 方法一 split分割 String fileName E file docx String temp fileName split String fileNameNow temp temp length 1 System ou
  • STM32——SPI通信

    文章目录 SPI Serial Peripheral Interface 概述 SPI的硬件连接 SPI的特点和优势 SPI的常见应用 SPI的工作方式和时序图分析 工作模式 传输模式与时序分析 工作流程 SPI设备的寄存器结构和寄存器设置
  • c++自定义类对象的初始化_类装载器

    一 类的生命周期 类从被加载到虚拟机内存中开始 直到从内存中卸载为止 它的整个生命周期包括了 加载 验证 准备 解析 初始化 使用和卸载这7个阶段 其中 验证 准备和解析这三个部分统称为链接 linking graph LR A 加载 gt
  • RedHat linux 9.1/CentOS linux YUM在线安装用不了? 不会配置Linux的网络安装源?一分钟教你解决!!!

    一 配置本地源 1 新建cdrom目录 root kongd mkdir media cdrom 2 将本地光盘挂载至本地目录 media cdrom下 root kongd mount dev cdrom media cdrom 3 新建
  • Unable to find instance for XXXX

    当你的控制台报了这样的错误 这就是请求的后端服务没启动 联系后端启动后端就行
  • dubbo之RpcContext

    dubbo之RpcContext RpcContext 是一个 ThreadLocal 的临时状态记录器 当接收到 RPC 请求 或发起 RPC 请求时 RpcContext 的状态都会变化 比如 A 调 B B 再调 C 则 B 机器上
  • matlab 判断数组中的元素是否存在,C语言判断数组中是否包含某个元素

    在实际开发中 经常需要查询数组中的元素 例如 学校为每位同学分配了一个唯一的编号 现在有一个数组 保存了实验班所有同学的编号信息 如果有家长想知道他的孩子是否进入了实验班 只要提供孩子的编号就可以 如果编号和数组中的某个元素相等 就进入了实
  • ODTK:来自NVIDIA的旋转框物体检测工具箱

    点击上方 AI公园 关注公众号 选择加 星标 或 置顶 作者 Jonathan Howe James Skinner 编译 ronghuaiyang 导读 旋转框相比矩形框可以更好的拟合物体 同时标注起来比分割要方便的多 使用来自NVIDI
  • k8s的初始及搭建

    kubernetes k8s 1 初识k8s 1 1 k8s是什么 kubernetes 简称K8s 是用8代替8个字符 ubernete 而成的缩写 是一个开源的 由go语言开发 用于管理云平台中多个主机上的容器化的应用 Kubernet
  • ElasticSearch 搜索引擎

    简称es 是类似于mysql但是专注于搜索的一种数据库 在elastic stack中占据重要地位 倒排索引 我们的数据库都是正向索引 比如根据id查询数据 那么倒排索引是将关键字进行分词 然后将词条和id保存在一张表中 不同数据分词后有相
  • retval释疑

    为了让方法返回一个与 方法的物理HRESULT 不相关的逻辑结果 COM IDL支持retval参数属性 retval属性的含义是 相关联的物理方法参数实际上是操作的逻辑结果 在支持retval的环境中 该参数应该被映射为操作的结果 例如
  • MyCAT 通过Native for MySQL 连接TESTDB 提示:1184 (HY000): Invalid DataSource:0

    问题描述 Windows 安装MyCAT服务 启动MyCAT服务 通过Native for MySQL 连接TESTDB 提示如下错误信息 1184 HY000 Invalid DataSource 0 造成问题原因 没有给root用户授予
  • 聚类尝试-kmeans-step2聚类模型训练及结果可视化

    step1 https blog csdn net nikita zj article details 122342746https blog csdn net nikita zj article details 122342746 1 数
  • python基础知识总结

    1 python相关 发布时间比java要早 1999年应用在网站后端开发 2004年发布web框架Django 2 特点 解释性语言 交互式语言 面向对象 跨平台 3 优点 易学 易读 易维护 有广泛标准库 互动模式 可嵌入性 嵌入C或者
  • 如何解决openstack中协程切换后request_id打印不对或者不打印的问题的

    OpenStack各组件一般都对外提供REST服务 当某个API请求过来之后 由于可能会涉及多个方法和进程的处理 为了方便的跟踪这个请求和后续通过日志定位 我们需要有个唯一标示来追踪这个请求 这样就能从大量日志信息中找到和这个请求相关的日志
  • Android开发之蓝牙(一)——基于SPP协议蓝牙模块通信

    使用设备 基本概念 基本流程 本文意在介绍蓝牙开发的主要流程 学习使用蓝牙开发一个星期了 写写一个星期以来遇到的一些小问题 还有介绍下流程 开发具有基本的通信功能 本项目主要是用于与蓝牙模块的串口读写功能 下一篇文章还有Android开发之