导航:首页 > 操作系统 > android蓝牙开发文档

android蓝牙开发文档

发布时间:2025-06-04 11:13:51

‘壹’ android-Ble蓝牙开发Demo示例–扫描,连接,发送和接收数据,分包解包(附源码)

万物互联的物联网时代的已经来临,ble蓝牙开发在其中扮演着举重若轻的角色。最近刚好闲一点,抽时间梳理下这块的知识点。

涉及ble蓝牙通讯的客户端(开启、扫描、连接、发送和接收数据、分包解包)和服务端(初始化广播数据、开始广播、配置Services、Server回调操作)整个环节以及一些常见的问题即踩过的一些坑。

比如
1、在Android不同版本或不同手机的适配问题,扫描不到蓝牙设备
2、如何避免ble蓝牙连接出现133错误?
3、单次写的数据大小有20字节限制,如何发送长数据

蓝牙有传统(经典)蓝牙和低功耗蓝牙BLE(Bluetooth Low Energy)之分,两者的开发的API不一样,本文主讲Ble蓝牙开发,传统蓝牙不展开,有需要的可以自行了解。

相对传统蓝牙,BLE低功耗蓝牙,主要特点是快速搜索,快速连接,超低功耗保持连接和数据传输。

客户端

服务端

Android4.3(API Level 18)开始引入BLE的核心功能并提供了相应的 API。应用程序通过这些 API 扫描蓝牙设备、查询 services、读写设备的 characteristics(属性特征)等操作。

BLE蓝牙协议是GATT协议, BLE相关类不多, 全都位于android.bluetooth包和android.bluetooth.le包的几个类:
android.bluetooth.
.BluetoothGattService 包含多个Characteristic(属性特征值), 含有唯一的UUID作为标识
.BluetoothGattCharacteristic 包含单个值和多个Descriptor, 含有唯一的UUID作为标识
.BluetoothGattDescriptor 对Characteristic进行描述, 含有唯一的UUID作为标识

.BluetoothGatt 客户端相关
.BluetoothGattCallback 客户端连接回调
.BluetoothGattServer 服务端相关
.BluetoothGattServerCallback 服务端连接回调

android.bluetooth.le.
.AdvertiseCallback 服务端的广播回调
.AdvertiseData 服务端的广播数据
.AdvertiseSettings 服务端的广播设置
.BluetoothLeAdvertiser 服务端的广播

.BluetoothLeScanner 客户端扫描相关(Android5.0新增)
.ScanCallback 客户端扫描回调
.ScanFilter 客户端扫描过滤
.ScanRecord 客户端扫描结果的广播数据
.ScanResult 客户端扫描结果
.ScanSettings 客户端扫描设置

BLE设备分为两种设备: 客户端(也叫主机/中心设备/Central), 服务端(也叫从机/外围设备/peripheral)
客户端的核心类是 BluetoothGatt
服务端的核心类是 BluetoothGattServer 和 BluetoothLeAdvertiser
BLE数据的核心类是 BluetoothGattCharacteristic 和 BluetoothGattDescriptor

下面详细讲解下客户端和服务端的开发步骤流程

安卓手机涉及蓝牙权限问题,蓝牙开发需要在AndroidManifest.xml文件中添加权限声明:

在搜索设备之前需要询问打开手机蓝牙:

注意: BLE设备地址是动态变化(每隔一段时间都会变化),而经典蓝牙设备是出厂就固定不变了!

通过扫描BLE设备,根据设备名称区分出目标设备targetDevice,下一步实现与目标设备的连接,在连接设备之前要停止搜索蓝牙;停止搜索一般需要一定的时间来完成,最好调用停止搜索函数之后加以100ms的延时,保证系统能够完全停止搜索蓝牙设备。停止搜索之后启动连接过程;

BLE蓝牙的连接方法相对简单只需调用connectGatt方法;

参数说明

与设备建立连接之后与设备通信,整个通信过程都是在BluetoothGattCallback的异步回调函数中完成;

BluetoothGattCallback中主要回调函数如下:

上述几个回调函数是BLE开发中不可缺少的;

当调用targetdDevice.connectGatt(context, false, gattCallback)后系统会主动发起与BLE蓝牙设备的连接,若成功连接到设备将回调onConnectionStateChange方法,其处理过程如下:

判断newState == BluetoothGatt.STATE_CONNECTED表明此时已经成功连接到设备;

mBluetoothGatt.discoverServices();

扫描BLE设备服务是安卓系统中关于BLE蓝牙开发的重要一步,一般在设备连接成功后调用,扫描到设备服务后回调onServicesDiscovered()函数,函数原型如下:

BLE蓝牙开发主要有负责通信的BluetoothGattService完成的。当且称为通信服务。通信服务通过硬件工程师提供的UUID获取。获取方式如下:

具体操作方式如下:

开启监听,即建立与设备的通信的首发数据通道,BLE开发中只有当客户端成功开启监听后才能与服务端收发数据。开启监听的方式如下:

BLE单次写的数据量大小是有限制的, 通常是20字节 ,可以尝试通过requestMTU增大,但不保证能成功。分包写是一种解决方案,需要定义分包协议,假设每个包大小20字节,分两种包,数据包和非数据包。对于数据包,头两个字节表示包的序号,剩下的都填充数据。对于非数据包,主要是发送一些控制信息。
监听成功后通过向 writeCharacteristic写入数据实现与服务端的通信。写入方式如下:

其中:value一般为Hex格式指令,其内容由设备通信的蓝牙通信协议规定;

若写入指令成功则回调BluetoothGattCallback中的onCharacteristicWrite()方法,说明将数据已经发送给下位机;

若发送的数据符合通信协议,则服务端会向客户端回复相应的数据。发送的数据通过回调onCharacteristicChanged()方法获取,其处理方式如下:

通过向服务端发送指令获取服务端的回复数据,即可完成与设备的通信过程;

当与设备完成通信之后之后一定要断开与设备的连接。调用以下方法断开与设备的连接:

源码上传在CSDN上了,有需要的可以借鉴。

=====> Android蓝牙Ble通讯Demo示例源码–扫描,连接,发送和接收数据,分包解包

BLE单次写的数据量大小是有限制的,通常是20字节,可以尝试通过requestMTU增大,但不保证能成功。分包写是一种解决方案,需要定义分包协议,假设每个包大小20字节,分两种包,数据包和非数据包。对于数据包,头两个字节表示包的序号,剩下的都填充数据。对于非数据包,主要是发送一些控制信息。
总体流程如下:
1、定义通讯协议,如下(这里只是个举例,可以根据项目需求扩展)

2、封装通用发送数据接口(拆包)
该接口根据会发送数据内容按最大字节数拆分(一般20字节)放入队列,拆分完后,依次从队列里取出发送

3、封装通用接收数据接口(组包)
该接口根据从接收的数据按协议里的定义解析数据长度判读是否完整包,不是的话把每条消息累加起来

4、解析完整的数据包,进行业务逻辑处理

5、协议还可以引入加密解密,需要注意的选算法参数的时候,加密后的长度最好跟原数据长度一致,这样不会影响拆包组包

一般都是Android版本适配以及不同ROM机型(小米/红米、华为/荣耀等)(EMUI、MIUI、ColorOS等)的权限问题

蓝牙开发中有很多问题,要静下心分析问题,肯定可以解决的,一起加油;

‘贰’ Android 蓝牙开发(三)-蓝牙的详细介绍

前面的两篇文章,主要是在 Android 官网关于蓝牙介绍的基础上加上自己的理解完成的。主要针对的是 Android 开发中的一些 API 的使用。
第一篇文章 Android 蓝牙开发(一) 主要是介绍了普通的蓝牙在 Android 开发中的运用。
第二篇文章 Android 蓝牙开发(二) 主要是介绍了低功耗蓝牙的开发。
这篇文章主要介绍的是蓝牙的历史和一些关于蓝牙的通用知识,还有广播包的知识。要想彻底了解蓝牙开发,这些基础的知识也是需要的,就像网络协议一样,这些都是基础的内容。我们的 API 的调用都是以这个为基础的,了解这些,开发过程中遇到问题,才可以知道什么怎么一回事。

下篇文章主要讲的就是实际开发中的一些坑。

蓝牙其实就是一种近距离无线通信技术。

从下到上分别为:控制器(Controller)-->主机(host)-->应用(Application)

详细介绍各个层的含义:

BLE 应用可以分为两大类:基于非连接的和基于连接的

意思就是外设和周边设备不发生连接,主要靠扫描到的广播来获取信息。发送广播的一方叫做 broadcaster 监听广播的一方叫做 oberver 在 GAP 层有对应的角色定义。

网络拓扑图:

这种方式就是广播设备不断的向外发送广播(含有特定的信息),然后观察者接受到广播按照两者之间约定好的协议进行解析拿到有用的信息。例如:iBeacon,通过这种设备我们可以实现室内定位。

其实这些设备的角色可以即使广播者又是观察者。接收到广播后作出了处理,然后又发送广播。这样就形成了双向的网络,类似于因特网,这就是蓝牙 Mesh 组网。

广播数据包格式:

每个广播数据包由 31 byte 组成。分为有效数据和无效数据两部分。

例子:

这里是扫描的数据包(转换成了 16 进制,两个代表一个字节),第一个字节是 02 表示后面的两个字节是数据部分,然后第二个字节是 01 表示了数据的类型。后面一个字节就是真正的数据了。这个广播数据单元就分析完了。下面就是另一个数据单元了。依次类推,关于数据类型的解释,官网有。

这是数据类型对应的含义表。

网络拓扑图:

一个中心设备可连接多个外设,但是一个外设只能连接一个中心(外设连接成功后就会停止对外广播,别人就发现不了它了)。其中一个中心设备的连接外设的数量也是有限的。

链接: https://mp.weixin.qq.com/s?__biz=MzU5NzA2NjQzMg==&mid=2247484141&idx=1&sn=&scene=21#wechat_redirect

‘叁’ Android 蓝牙开发(一)

普通蓝牙设备官方文档

Android 平台包含蓝牙网络堆栈支持 ,凭借此支持,设备能以无线方式与其他蓝牙设备交换数据。应用框架提供了通过 Android Bluetooth API 访问蓝牙功能的途径。使用 Bluetooth API Android 应用可以执行下面的操作:

传统蓝牙适用于电池使用强度较大的操作,例如 Android 设备之间的流传输和通信等。针对具有低功耗要求的蓝牙设备,Android 4.3(API 18)中引入了面向低功耗蓝牙的 API 支持。

使用 Android Bluetooth API 来完成使用蓝牙进行通信的四项主要任务: 设置蓝牙 、 查找局部区域内的配对设备或可用设备 、 连接设备 ,以及在 设备之间传输数据 。

关于蓝牙的 API 在 android.bluetooth 包中,下面介绍一下和蓝牙相关的主要类:

在 BluetoothProfile IPC 客户端连接到服务(即,运行特定配置文件的内部服务)或断开服务连接时向其发送通知的接口。

使用蓝牙必须声明权限 BLUETOOTH 才可以执行蓝牙通信。

1、获取蓝牙适配器

例如:我们可以查询所有已配对的设备,然后使用 ArrayAdapter 向用户显示每台设备的名称:

要发起连接仅需要知道目标蓝牙设备的 Mac 地址就可以了。

注意 执行 discovery 对于蓝牙适配器来说是一个非常繁重的过程,并且会消耗大量资源。在找到要连接的设备后, 要确保使用 cancelDiscovery() 来停止发现,然后尝试连接 。如果您已经和某台设备进行连接,那么这个时候执行发现操作会大幅度的减少此连接可用的带宽!因此不应该在处于连接状态的时候执行发现操作!

例如:

在连接之前如果两个设备没有配对,则系统会自动发出配对请求。

服务器套接字接受连接的基本过程

放在子线程中去执行。

例子:

客户端连接的基本过程

调用 connect() 的时候要确保客户端没有执行发现操作。如果执行了会大幅度降低连接的速度,增加失败的可能。

例子

在连接之前调用 cancleDiscovery() 在进行连接之前应该始终调用这个方法,而且调用的时候无需检测是否正在扫描。

过程:

从 Android 3.0 开始, Bluetooth API 便支持使用蓝牙配置文件。蓝牙配置文件是适用于设备间蓝牙通信的无线接口规范。

1、蓝牙配置文件就是设备间通信(蓝牙设备)的一种规范

免提配置文件便是一个示例,对于连接到无线耳机的手机,两台设备都必须支持免提配置文件。我们也可以通过实现接口 BluetoothProfile 来写入自己的类来支持特定的蓝牙配置文件。Android API 提供了以下的几种蓝牙配置文件的实现:

2、使用配置文件的基本步骤

创建 HDP 应用:

关于普通蓝牙设备和普通蓝牙设备之间的连接通信

关于蓝牙设备和蓝牙仪器(蓝牙耳机、电子秤等等类似产品)
这种之间的通信是通过配置文件代理来实现的。
都有一个对应的配置文件代理类。具体的操作是通过这个对象来完成。

参考: https://mp.weixin.qq.com/s?__biz=MzU5NzA2NjQzMg==&mid=2247484128&idx=1&sn=&scene=21#wechat_redirect

‘肆’ 如何实现android蓝牙开发 自动配对连接,并不弹出提示框

我就开始查找怎么关闭这个蓝牙配对提示框,后面还是伟大的android源码帮助了我。
在源码 BluetoothDevice 类中还有两个隐藏方法
cancelBondProcess()和cancelPairingUserInput()
这两个方法一个是取消配对进程一个是取消用户输入
下面是自动配对的代码
Mainfest,xml注册

<receiverandroid:name=".">

<intent-filter>

<actionandroid:name="android.bluetooth.device.action.PAIRING_REQUEST"/>

</intent-filter>

</receiver>

自己在收到广播时处理并将预先输入的密码设置进去

java">
{

StringstrPsw="0";

@Override
publicvoidonReceive(Contextcontext,Intentintent)
{
//TODOAuto-generatedmethodstub
if(intent.getAction().equals(
"android.bluetooth.device.action.PAIRING_REQUEST"))
{
BluetoothDevicebtDevice=intent
.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);

//byte[]pinBytes=BluetoothDevice.convertPinToBytes("1234");
//device.setPin(pinBytes);
Log.i("tag11111","ddd");
try
{
ClsUtils.setPin(btDevice.getClass(),btDevice,strPsw);//手机和蓝牙采集器配对
ClsUtils.createBond(btDevice.getClass(),btDevice);
ClsUtils.cancelPairingUserInput(btDevice.getClass(),btDevice);
}
catch(Exceptione)
{
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
}


}
}
<b>/************************************蓝牙配对函数***************/
importjava.lang.reflect.Field;
importjava.lang.reflect.Method;

importandroid.bluetooth.BluetoothDevice;
importandroid.util.Log;
publicclassClsUtils
{

/**
*与设备配对参考源码:platform/packages/apps/Settings.git
*/Settings/src/com/android/settings/bluetooth/CachedBluetoothDevice.java
*/
staticpublicbooleancreateBond(ClassbtClass,BluetoothDevicebtDevice)
throwsException
{
MethodcreateBondMethod=btClass.getMethod("createBond");
BooleanreturnValue=(Boolean)createBondMethod.invoke(btDevice);
returnreturnValue.booleanValue();
}

/**
*与设备解除配对参考源码:platform/packages/apps/Settings.git
*/Settings/src/com/android/settings/bluetooth/CachedBluetoothDevice.java
*/
staticpublicbooleanremoveBond(ClassbtClass,BluetoothDevicebtDevice)
throwsException
{
MethodremoveBondMethod=btClass.getMethod("removeBond");
BooleanreturnValue=(Boolean)removeBondMethod.invoke(btDevice);
returnreturnValue.booleanValue();
}

staticpublicbooleansetPin(ClassbtClass,BluetoothDevicebtDevice,
Stringstr)throwsException
{
try
{
MethodremoveBondMethod=btClass.getDeclaredMethod("setPin",
newClass[]
{byte[].class});
BooleanreturnValue=(Boolean)removeBondMethod.invoke(btDevice,
newObject[]
{str.getBytes()});
Log.e("returnValue",""+returnValue);
}
catch(SecurityExceptione)
{
//thrownewRuntimeException(e.getMessage());
e.printStackTrace();
}
catch(IllegalArgumentExceptione)
{
//thrownewRuntimeException(e.getMessage());
e.printStackTrace();
}
catch(Exceptione)
{
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
returntrue;

}

//取消用户输入
(ClassbtClass,
BluetoothDevicedevice)

throwsException
{
MethodcreateBondMethod=btClass.getMethod("cancelPairingUserInput");
//cancelBondProcess()
BooleanreturnValue=(Boolean)createBondMethod.invoke(device);
returnreturnValue.booleanValue();
}

//取消配对
(ClassbtClass,
BluetoothDevicedevice)

throwsException
{
MethodcreateBondMethod=btClass.getMethod("cancelBondProcess");
BooleanreturnValue=(Boolean)createBondMethod.invoke(device);
returnreturnValue.booleanValue();
}

/**
*
*@paramclsShow
*/
(ClassclsShow)
{
try
{
//取得所有方法
Method[]hideMethod=clsShow.getMethods();
inti=0;
for(;i<hideMethod.length;i++)
{
Log.e("methodname",hideMethod[i].getName()+";andtheiis:"
+i);
}
//取得所有常量
Field[]allFields=clsShow.getFields();
for(i=0;i<allFields.length;i++)
{
Log.e("Fieldname",allFields[i].getName());
}
}
catch(SecurityExceptione)
{
//thrownewRuntimeException(e.getMessage());
e.printStackTrace();
}
catch(IllegalArgumentExceptione)
{
//thrownewRuntimeException(e.getMessage());
e.printStackTrace();
}
catch(Exceptione)
{
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
}
}</b>
执行时直接使用:
<b>publicstaticbooleanpair(StringstrAddr,StringstrPsw)
{
booleanresult=false;
=BluetoothAdapter
.getDefaultAdapter();

bluetoothAdapter.cancelDiscovery();

if(!bluetoothAdapter.isEnabled())
{
bluetoothAdapter.enable();
}

if(!BluetoothAdapter.checkBluetoothAddress(strAddr))
{//检查蓝牙地址是否有效

Log.d("mylog","devAdneffient!");
}

BluetoothDevicedevice=bluetoothAdapter.getRemoteDevice(strAddr);

if(device.getBondState()!=BluetoothDevice.BOND_BONDED)
{
try
{
Log.d("mylog","NOTBOND_BONDED");
ClsUtils.setPin(device.getClass(),device,strPsw);//手机和蓝牙采集器配对
ClsUtils.createBond(device.getClass(),device);
remoteDevice=device;//配对完毕就把这个设备对象传给全局的remoteDevice
result=true;
}
catch(Exceptione)
{
//TODOAuto-generatedcatchblock

Log.d("mylog","setPiNfailed!");
e.printStackTrace();
}//

}
else
{
Log.d("mylog","HASBOND_BONDED");
try
{
ClsUtils.createBond(device.getClass(),device);
ClsUtils.setPin(device.getClass(),device,strPsw);//手机和蓝牙采集器配对
ClsUtils.createBond(device.getClass(),device);
remoteDevice=device;//如果绑定成功,就直接把这个设备对象传给全局的remoteDevice
result=true;
}
catch(Exceptione)
{
//TODOAuto-generatedcatchblock
Log.d("mylog","setPiNfailed!");
e.printStackTrace();
}
}
returnresult;
}</b>

‘伍’ Android蓝牙开发——实现蓝牙聊天

与蓝牙开发主要的相关类是以下四个

知道对应API后就可以进行对应的蓝牙开发,这里以获取蓝牙设备为例子

}

搜索设备的回调则需要通过注册广播的形式来获取

定义广播

之后就可以进行个人的一些操作

要实现蓝牙聊天则涉及到蓝牙之间的传输通信,前面也说到了,这里肯定就是用到BluetoothServerSocket以及BluetoothSocket。

蓝牙传输通信相当于服务器端与客户端之间的通信,只不过不同是这里每一个蓝牙设备本身自己 既充当服务器端也充当客户端 ,大致的关系就是

注意,这些连接都是阻塞式的,都要放在线程里去执行。

可以看到,当BluetoothServerSocket监听到有设备连接的时候,就会调用dataTransfer开启一个数据传输。

需要一个ConnectThread来发起

之后建立连接之后就会调用dataTransfer来进行数据传输,同样也需要一个线程来维护数据传输

蓝牙聊天则是基于上面三个线程来进行实现,同样,对于蓝牙文件间的传输也是同个道理,通过输入输出流来进行处理。之后的操作就比较容易处理了

蓝牙聊天

Android 蓝牙开发基本流程

‘陆’ 如何使用Android蓝牙开发

转载 Android平台支持蓝牙网络协议栈,实现蓝牙设备之间数据的无线传输。本文档描述了怎样利用android平台提供的蓝牙API去实现蓝压设备之间的通信。蓝牙具有point-to-point 和 multipoint两种连接功能。
使用蓝牙API,可以做到:
* 搜索蓝牙设备
* 从本地的Bluetooth adapter中查询已经配对的设备
* 建立RFCOMM通道
* 通过service discovery连接到其它设备
* 在设备之间传输数据
* 管理多个连接

基础知识
本文档介绍了如何使用Android的蓝牙API来完成的四个必要的主要任务,使用蓝牙进行设备通信,主要包含四个部分:蓝牙设置、搜索设备(配对的或可见的)、连接、传输数据。
所有的蓝牙API在android.bluetooth包中。实现这些功能主要需要下面这几个类和接口:

BluetoothAdapter
代表本地蓝牙适配器(蓝牙发射器),是所有蓝牙交互的入口。通过它可以搜索其它蓝牙设备,查询已经配对的设备列表,通过已知的MAC地址创建BluetoothDevice,创建BluetoothServerSocket监听来自其它设备的通信。

BluetoothDevice
代表了一个远端的蓝牙设备, 使用它请求远端蓝牙设备连接或者获取 远端蓝牙设备的名称、地址、种类和绑定状态。 (其信息是封装在 bluetoothsocket 中) 。

BluetoothSocket
代表了一个蓝牙套接字的接口(类似于 tcp 中的套接字) ,他是应用程 序通过输入、输出流与其他蓝牙设备通信的连接点。

BluetoothServerSocket
代表打开服务连接来监听可能到来的连接请求 (属于 server 端) , 为了连接两个蓝牙设备必须有一个设备作为服务器打开一个服务套接字。 当远端设备发起连 接连接请求的时候,并且已经连接到了的时候,Blueboothserversocket 类将会返回一个 bluetoothsocket。

BluetoothClass
描述了一个设备的特性(profile)或该设备上的蓝牙大致可以提供哪些服务(service),但不可信。比如,设备是一个电话、计算机或手持设备;设备可以提供audio/telephony服务等。可以用它来进行一些UI上的提示。
BluetoothProfile

BluetoothHeadset
提供手机使用蓝牙耳机的支持。这既包括蓝牙耳机和免提(V1.5)模式。

BluetoothA2dp
定义高品质的音频,可以从一个设备传输到另一个蓝牙连接。 “A2DP的”代表高级音频分配模式。

BluetoothHealth
代表了医疗设备配置代理控制的蓝牙服务

BluetoothHealthCallback
一个抽象类,使用实现BluetoothHealth回调。你必须扩展这个类并实现回调方法接收更新应用程序的注册状态和蓝牙通道状态的变化。


代表一个应用程序的配置,蓝牙医疗第三方应用注册与远程蓝牙医疗设备交流。

BluetoothProfile.ServiceListener
当他们已经连接到或从服务断开时通知BluetoothProfile IPX的客户时一个接口(即运行一个特定的配置文件,内部服务)。

蓝牙权限
为了在你的应用中使用蓝牙功能,至少要在AndroidManifest.xml中声明两个权限:BLUETOOTH(任何蓝牙相关API都要使用这个权限) 和 BLUETOOTH_ADMIN(设备搜索、蓝牙设置等)。

为了执行蓝牙通信,例如连接请求,接收连接和传送数据都必须有BLUETOOTH权限。

必须要求BLUETOOTH_ADMIN的权限来启动设备发现或操纵蓝牙设置。大多数应用程序都需要这个权限能力,发现当地的蓝牙设备。此权限授予其他的能力不应该使用,除非应用程序是一个“电源管理”,将根据用户要求修改的蓝牙设置

注释:要请求BLUETOOTH_ADMIN的话,必须要先有BLUETOOTH。

在你的应用manifest 文件中声明蓝牙权限。例如:

<manifest ... >
<uses-permission android:name="android.permission.BLUETOOTH" />
...
</manifest>
通过查看<uses-permission>资料来声明应用权限获取更多的信息。

蓝牙设置
在你的应用通过蓝牙进行通信之前,你需要确认设备是否支持蓝牙,如果支持,确信它被打开。

如果不支持,则不能使用蓝牙功能。如果支持蓝牙,但不能够使用,你刚要在你的应用中请求使用蓝牙。这个要两步完成,使用BluetoothAdapter。

1.获取BluetoothAdapter

所有的蓝牙活动请求BluetoothAdapter,为了获取BluetoothAdapter,呼叫静态方法getDefaultAdapter() 。这个会返回一个BluetoothAdapter,代表设备自己的蓝牙适配器(蓝牙无线电)。这个蓝牙适配器应用于整个系统中,你的应用可以通过这个对象进行交互。如果getDefaultAdapter()返回null,则这个设备不支持蓝牙。例如:

BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter == null) {
// Device does not support Bluetooth
}
2.打开蓝牙

其次。你需要确定蓝牙能够使用。通过isEnabled()来检查蓝牙当前是否可用。如果这个方法返回false,则蓝牙不能够使用。为了请求蓝牙使用,呼叫startActivityForResult()与的ACTION_REQUEST_ENABLE动作意图。通过系统设置中启用蓝牙将发出一个请求(不停止蓝牙应用)。例如:

if (mBluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
![http://developer.android.com/images/bt_enable_request.png]

对话框中显示请求使用蓝牙权限。如果响应"Yes",这个进程完成(或失败)后你的应用将能够使用蓝牙。
REQUEST_ENABLE_BT常量作为一个整型传到startActivityForResult()中(值必须大于0),该系统传回给你,在你onActivityResult()作为实现的requestCode参数。

如果调用蓝牙成功,你的Activity就会在onActivityResult()中收到RESULT_OK结果,如果蓝牙不能使用由于错误(或用户响应“NO”那么结果返回RESULT_CANCELED。

除了通过onActivityResult(),还可以通过监听ACTION_STATE_CHANGED这个broadcast Intent来知道蓝牙状态是否改变。这个Intent包含EXTRA_STATE,EXTRA_PREVIOUS_STATE两个字段,分别代表新旧状态。可能的值是STATE_TURNING_ON, STATE_ON, STATE_TURNING_OFF, 还有STATE_OFF。

小贴: Enabling discoverability 将自动启用蓝牙。如果您计划执行蓝牙活动之前,始终使设备可发现,你可以跳过上面的步骤2。参阅enabling discoverability。

搜索设备
使用BluetoothAdapter可以通过设备搜索或查询配对设备找到远程Bluetooth设备。

Device discovery(设备搜索)是一个扫描搜索本地已使能Bluetooth设备并且从搜索到的设备请求一些信息的过程(有时候会收到类似“discovering”,“inquiring”或“scanning”)。但是,搜索到的本地Bluetooth设备只有在打开被发现功能后才会响应一个discovery请求,响应的信息包括设备名,类,唯一的MAC地址。发起搜寻的设备可以使用这些信息来初始化跟被发现的设备的连接。
一旦与远程设备的第一次连接被建立,一个pairing请求就会自动提交给用户。如果设备已配对,配对设备的基本信息(名称,类,MAC地址)就被保存下来了,能够使用Bluetooth API来读取这些信息。使用已知的远程设备的MAC地址,连接可以在任何时候初始化而不必先完成搜索(当然这是假设远程设备是在可连接的空间范围内)。

需要记住,配对和连接是两个不同的概念:

配对意思是两个设备相互意识到对方的存在,共享一个用来鉴别身份的链路键(link-key),能够与对方建立一个加密的连接。

连接意思是两个设备现在共享一个RFCOMM信道,能够相互传输数据。

目前Android Bluetooth API's要求设备在建立RFCOMM信道前必须配对(配对是在使用Bluetooth API初始化一个加密连接时自动完成的)。

下面描述如何查询已配对设备,搜索新设备。

注意:Android的电源设备默认是不能被发现的。用户可以通过系统设置让它在有限的时间内可以被发现,或者可以在应用程序中要求用户使能被发现功能。

查找匹配设备
在搜索设备前,查询配对设备看需要的设备是否已经是已经存在是很值得的,可以调用getBondedDevices()来做到,该函数会返回一个描述配对设备BluetoothDevice的结果集。例如,可以使用ArrayAdapter查询所有配对设备然后显示所有设备名给用户:

Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
// If there are paired devices
if (pairedDevices.size() > 0) {
// Loop through paired devices
for (BluetoothDevice device : pairedDevices) {
// Add the name and address to an array adapter to show in a ListView
mArrayAdapter.add(device.getName() + "n" + device.getAddress());
}
};
BluetoothDevice对象中需要用来初始化一个连接唯一需要用到的信息就是MAC地址。

‘柒’ Android开发之蓝牙(Bluetooth)

在上一篇中有介绍了Wifi与网络连接处理
Android开发之WiFi与网络连接处理
下面,来继续说说Android中蓝牙的基本使用。

Bluetooth是目前使用的最广泛的无线通讯协议之一,主要针对短距离设备通讯(10米),常用于连接耳机、鼠标和移动通讯设备等。

值得一提的是:
android4.2新增了部分新功能,但是对于Bluetooth熟悉的人或许开始头疼了,那就是Android4.2引入了一个新的蓝牙协议栈针BLE。谷歌和Broadcom之间的合作,开发新的蓝牙协议栈,取代了基于堆栈的Bluez。因此市场上出现了老设备的兼容问题,很多蓝牙设备在android4.2手机上不能正常使用。

BluetoothAdapter简单点来说就是代表了本设备(手机、电脑等)的蓝牙适配器对象。

first:we need permission
要操作蓝牙,先要在AndroidManifest.xml里加入权限

**下面来看看如何使用蓝牙。 **↓↓↓****
Demo已就绪:

返回值:如果设备具备蓝牙功能,返回BluetoothAdapter 实例;否则,返回null对象。

打开蓝牙设备的方式:
1.直接调用函数enable()去打开蓝牙设备 ;
2.系统API去打开蓝牙设备,该方式会弹出一个对话框样式的Activity供用户选择是否打开蓝牙设备。

注意: 1.如果蓝牙已经开启,不会弹出该Activity界面。2.在目前大多数Android手机中,是不支持在飞行模式下开启蓝牙的。如果蓝牙已经开启,那么蓝牙的开关 ,状态会随着飞行模式的状态而发生改变。

1. 搜索蓝牙设备
使用BluetoothAdapter的startDiscovery()方法来搜索蓝牙设备
startDiscovery()方法是一个异步方法,调用后会立即返回。该方法会进行对其他蓝牙设备的搜索,该过程会持续12秒。该方法调用后,搜索过程实际上是在一个System Service中进行的,所以可以调用cancelDiscovery()方法来停止搜索(该方法可以在未执行discovery请求时调用)。

系统开始搜索蓝牙设备
^( *  ̄(oo) ̄ ) ^ 系统会发送以下三个广播:

2.扫描设备

3.定义广播接收器接收搜索结果

4.注册广播

获取附近的蓝牙设备

第一步建立连接:首先Android sdk(2.0以上版本)支持的蓝牙连接是通过BluetoothSocket建立连接,服务端BluetoothServerSocket和客户端(BluetoothSocket)需指定同样的UUID,才能建立连接,因为建立连接的方法会阻塞线程,所以服务器端和客户端都应启动新线程连接。

(这里的服务端和客户端是相对来说的)
两个蓝牙设备之间的连接,则必须实现服务端与客户端的机制。
当两个设备在同一个RFCOMM channel下分别拥有一个连接的BluetoothSocket,这两个设备才可以说是建立了连接。

服务端设备与客户端设备获取BluetoothSocket的途径是不同的。
1,服务端设备是通过accepted一个incoming connection来获取的,
2,客户端设备则是通过打开一个到服务端的RFCOMM channel来获取的。

服务端
通过调用BluetoothAdapter的(String, UUID)方法来获取BluetoothServerSocket(UUID用于客户端与服务端之间的配对)

客户端
调用BluetoothService的(UUID)方法获取BluetoothSocket(该UUID应该同于服务端的UUID)。
调用BluetoothSocket的connect()方法(该方法为block方法),如果UUID同服务端的UUID匹配,并且连接被服务端accept,则connect()方法返回。

数据传递,通过以上操作,就已经建立的BluetoothSocket连接了,数据传递无非是通过流的形式
获取流

该类就是关于远程蓝牙设备的一个描述。通过它可以和本地蓝牙设备---BluetoothAdapter连接通信。

好多东西我也不知道怎么描述,下面给出Demo:
刚好有刚学习的小伙伴问我ListView怎么用,那我就用ListView。

源码:
RairDemo
GitHub: https://github.com/Rairmmd/android-demo
Coding: https://coding.net/u/Rair/p/RairDemo/git

‘捌’ 如何实现android蓝牙自动配对连接

在Android设备上实现蓝牙自动配对连接涉及多个步骤。首先,你需要获取BluetoothAdapter实例,这通过BluetoothAdapter.getDefaultAdapter()实现。如果返回值为null,说明手机不支持蓝牙功能。

接下来,检查蓝牙是否已经开启,使用blueadapter.isEnabled()方法。如果返回false,需要开启蓝牙。

为了让设备进入可配对模式,你需要启动一个配置蓝牙可见性的Intent。这一步骤通过创建Intent对象,并设置EXTRA_DISCOVERABLE_DURATION参数来实现,200秒表示设备在200秒内保持可见。

在AndroidManifest.xml文件中,你需要声明使用蓝牙权限,否则可能会遇到权限拒绝的错误。

自动配对过程需要设置Pin值。这里提供了一个静态方法autoBond,它接收蓝牙设备类、蓝牙设备实例和Pin值作为参数。通过反射调用蓝牙设备的setPin方法来设置Pin值。

最后,通过createBond方法发起配对请求。这也是通过反射调用蓝牙设备的createBond方法实现。这个方法返回一个布尔值,表示配对是否成功。

在进行自动配对连接时,务必确保蓝牙设备支持此类操作,并在测试环境中进行充分测试。此外,处理蓝牙连接时还需注意异常情况,确保程序的健壮性。

以上步骤详细介绍了如何在Android上实现蓝牙自动配对连接,适用于需要频繁进行蓝牙设备连接的应用场景。

实现自动配对连接后,你可以通过监听BluetoothDevice的连接状态变化来进一步优化用户体验,例如,在设备成功连接时触发特定操作。

值得注意的是,自动配对连接的成功与否取决于多种因素,包括蓝牙设备的兼容性、配对过程中的干扰等。

此外,确保在用户首次使用应用时,明确提示他们启用蓝牙功能,并告知自动配对连接的具体步骤,以提高用户体验。

阅读全文

与android蓝牙开发文档相关的资料

热点内容
程序员老年人 浏览:251
无线加密狗教程 浏览:761
十年前的安卓机还能干什么 浏览:255
怎么到文件夹找到王者回放 浏览:624
ad字体文件放在哪个文件夹 浏览:127
界面和算法并行设计 浏览:387
oa安卓系统叫什么 浏览:845
两用u盘加密 浏览:118
文件如何解压再压缩 浏览:622
使用编译命令导入库 浏览:118
app一般用什么服务器 浏览:821
手机端java编译 浏览:147
电脑文件夹一右键就卡 浏览:196
javalistforeach 浏览:28
奇葩解压笔 浏览:335
php判断字符串开头 浏览:270
多个pdf合并成一个pdf 浏览:735
linuxc获取mac 浏览:966
linux线程运行时间 浏览:381
机器人逆运算算法 浏览:304