Android - 蓝牙开发

科普

https://zh.wikipedia.org/wiki/%E8%97%8D%E7%89%99

蓝牙(英语:Bluetooth),一种无线通讯技术标准,用来让固定与移动设备,在短距离间交换资料,以形成个人局域网(PAN)。其使用短波特高频(UHF)无线电波,经由 2.4 至 2.485 GHz 的 ISM(工业、科学、医疗)频段来进行通信。1994 年由电信商爱立信(Ericsson)发展出这个技术。它最初的设计,是希望创建一个 RS-232 数据线的无线通信替代版本。它能够链接多个设备,克服同步的问题。

SIG

蓝牙技术联盟(英语:Bluetooth Special Interest Group,缩写为SIG)拥有蓝牙的商标,负责制定蓝牙规范、认证制造厂商,授权他们使用蓝牙技术与蓝牙标志,但本身不负责蓝牙设备的设计、生产及贩售。

类型

Classic Bluetooth(也称作 Bluetooth Basic Rate/Enhanced Data Rate (BR/EDR))、Bluetooth Low Energy(蓝牙 4.0 及更高版本)

EDR:一种更快的 PSK(Phase Shift Keying 相移键控,其他还有幅移键控、频移键控、最小移频键控、高斯滤波最小移频键控、QAM 正交幅度、OFDM 正交频分复用) 调制方案,能够比以前的蓝牙版本快 2 或 3 倍的速度传输数据。

https://www.bluetooth.com/learn-about-bluetooth/tech-overview/

制式

分 Single mode 与 Dual mode。
Single mode 只能与 BT4.0 互相传输无法向下兼容(与 3.0/2.1/2.0 无法相通);Dual mode 可以向下兼容,可与 BT4.0 传输也可以跟 3.0/2.1/2.0 传输

选择

蓝牙 LE 设备(v4 及更高版本)通常向后兼容(可在新版使用)。也就是说,两种类型的蓝牙,经典 (< v4) 和 LE (> v4),彼此完全不同。

经典蓝牙与经典的主从连接一起工作,其中一个设备向另一个设备发送指令,另一个设备服从。

低功耗蓝牙彻底改变了这一点,并用以客户端-服务器为中心的架构取代了该架构。设备采用 GATT 连接的思想,它们具有由服务和特征决定的特定规则和功能。您获得设备的服务通道,挂钩特定特征并读取/写入/订阅来自它的通知。这种新的连接类型允许外围设备仅在被调用时才起作用,从而减少了服务器端不断轮询连接的需要,节省了能源。它还允许您一次连接到多个 BLE 设备。

蓝牙设备被检测为低功耗和具有相同 MAC 地址和名称的普通蓝牙设备

经典蓝牙:蓝牙最初的设计意图,是打电话放音乐。3.0 版本以下的蓝牙,都称为“经典蓝牙”。功耗高、传输数据量大、传输距离只有 10 米。适用于传输音视频等数据量大或需要连续宽带链接的鼠标和其他设备的应用场合。

低功耗蓝牙:就是 BLE,通常说的蓝牙 4.0(及以上版本)。低功耗,数据量小,距离 50 米左右。使用于电池供电、连手机 APP 读取设备信息等应用场合。

逻辑链路控制适配协议 (L2CAP)

逻辑链路控制和适配协议 (L2CAP) 是蓝牙标准中使用的一种协议,它提供更高层和蓝牙堆栈基带层之间的适配。它在主机控制器接口 (HCI) 上方运行,将数据帧从更高层传递到 HCI 或链路管理器。

下图显示了 L2CAP 在蓝牙协议架构中的位置 -

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TabZDDmM-1635124900565)(https://www.tutorialspoint.com/assets/questions/media/38818/link_control_adaptation.jpg)]

L2CAP的功能

  • 蓝牙协议栈高层帧与低层帧的适配。
  • 支持面向连接和无连接服务。
  • 支持基带层的两个链接 -
    • 面向使用保留带宽的实时语音流量的同步面向连接 (SCO) 链接。
    • 用于尽力而为流量的异步无连接 (ACL) 链接。
  • 上层协议的复用,允许它们使用下层提供的链路。
  • 对大于下层无线电层容量的上层数据包进行分段和重组。
  • 集团管理。
  • 上层协议的服务质量 (QoS)。

蓝牙框架和 RFCOMM 协议

蓝牙 RFCOMM(射频通信)协议是一组简单的传输协议,建立在 L2CAP 协议之上,提供仿真 RS-232 串行端口。当不想处理串行接口信令问题时使用封装了 L2CAP 的 RFCOMM。

蓝牙安全

蓝牙安全漏洞与攻击 蓝牙技术的安全漏洞及攻击方法分析

白名单机制

所谓的白名单,就是一组蓝牙地址;

通过白名单,可以只允许特定的蓝牙设备(白名单中列出的)扫描(Scan)、连接(connect)我们;
我们也可以只扫描、连接特定的蓝牙设备(白名单中列出的)。

编程

Bluetooth Classic vs. Bluetooth Low Energy (BLE) on Android – Hints & Implementation Steps
Android-经典蓝牙(BT)-建立长连接传输短消息和文件
BLE与蓝牙科普
Android蓝牙健康设备开发:Health Device Profile(HDP)
Android蓝牙开发—经典蓝牙和BLE(低功耗)蓝牙的区别
Android低功耗蓝牙(BLE)开发的一点感受
【经验】低功耗蓝牙模块如何实现数据传输?

Classic Bluetooth 和 Bluetooth Low Energy 开发有很大的区别。

连接:
Classic Bluetooth 建立连接的方式实际上就是 Socket 的连接的建立,利用搜索找到的 BluetoothDevice,调用其方法 createRfcommSocketToServiceRecord(UUID)。最后,使用获取到的 BluetoothDevice 调用其方法 connect()。

Bluetooth Low Energy 建立连接的方式类似于数据库的连接。通过 BluetoothAdapter 的 getRemoteDevice(address) 方法获取相应 BLE 从设备的 BluetoothDevice,其中的 address 为目标蓝牙设备 MAC 地址。然后通过此 BluetoothDevice 的 connectGatt(this, false, mGattCallback) 方法获取设备连接以及返回属性句柄来访问 Gatt 数据库。此时的连接,只能够进行监听,也就是获取到当前BLE从设备广播出来的数据。

读写:
Classic Bluetooth 使用 BluetoothSocket 的 getOutputStream() 方法获取输出流写入需要发送的数据,调用 BluetoothSocket 的 getInputStream() 方法获取输入流读取。

Bluetooth Low Energy 想要实现主设备对从设备的数据发送,则需要直接读取获取到的从设备的 Characteristic。

蓝牙权限

BLUETOOTH:(必需),例如请求连接、接受连接和传输数据。
BLUETOOTH_ADMIN:(可选),如果您希望您的应用程序启动设备发现或操作蓝牙设置、创建套接字连接,除了 BLUETOOTH 权限之外,您还必须声明此权限。大多数应用程序作为连接的主动方需要此权限仅用于发现本地蓝牙设备。
ACCESS_FINE_LOCATION:(必需),因为蓝牙扫描需要收集有关用户位置的信息。该信息可能来自用户自己的设备,以及在商店和交通设施等位置使用的蓝牙信标。

由于 ACCESS_FINE_LOCATION危险权限,你需要在清单中声明它并 在运行时请求此权限

Note: Android 9(API 级别 28)或更低版本,需要声明 ACCESS_COARSE_LOCATION 而不是 ACCESS_FINE_LOCATION 权限。

Note: Android 10 及更高版本,需要拥有 ACCESS_BACKGROUND_LOCATION 权限才能发现蓝牙设备。有关此要求的更多信息,请参阅 后台访问位置
使用 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) 条件判断该版本。

Note: Android 8.0(API 级别 26)及更高版本,可以使用 CompanionDeviceManager 对附近的配套设备执行扫描,而无需位置权限。有关此选项的更多信息,请参阅 配套设备配对

如果您希望您的应用程序启动设备发现或操作蓝牙设置,除了 BLUETOOTH 权限之外,您还必须声明 BLUETOOTH_ADMIN 权限。

Classic Bluetooth

https://developer.android.com/guide/topics/connectivity/bluetooth
https://developer.android.com/guide/topics/connectivity/bluetooth?hl=zh-cn

Bluetooth Low Energy

蓝牙低功耗概览
低功耗蓝牙
Android BluetoothLeGatt Sample
The Ultimate Guide to Android Bluetooth Low Energy:Android 低功耗蓝牙终极指南!

术语

Generic Attribute Profile (GATT):通用属性配置文件 是解释如何在 BLE 链路发送和接收“属性”短数据段的通用规范。当前所有的 BLE 应用配置文件都是基于 GATT 通过“属性”进行交流。一个设备可以实现多个服务的配置文件。例如,一台设备可能包含心率监测仪和电池电量检测器。
Attribute Protocol (ATT):GATT 建立在属性协议 (ATT) 之上,二者的关系也被称为 GATT/ATT。该协议为在 BLE 设备上运行进行优化,使用尽可能少的字节。每个属性均由通用唯一标识符 (UUID) 进行唯一标识,按照 Service - Characteristic 的格式传输。
Characteristic:特征 包含一个特征值以及 0-n 个描述此特征值的 Descriptor,相当于一个类。
Descriptor:描述符 是已定义的描述特征值的属性。例如,描述符可指定特征值的可接受范围或特定于特征值的度量单位。
Service:服务 是特征的集合。例如,在名为“心率监测器”的服务中包括“心率测量”等特征。在 bluetooth.org 上可查看现有的 GATT 配置文件及服务的列表。

角色 & 职能

在 BLE 连接中,中央(主)设备进行扫描、寻找广播;外围(从)设备发出广播。
在 BLE 数据传输中,发送数据的设备充当 Gatt 服务器,接收数据的设备充当 Gatt 客户端。

查找 BLE 设备

使用 startLeScan() 方法,将 BluetoothAdapter.LeScanCallback 作为参数。必须实现此回调。扫描非常耗电,要设置扫描时间限制;找到所需设备后,立即停止扫描。

以下代码段展示如何启动和停止扫描:

/**
 * Activity for scanning and displaying available BLE devices.
 */
public class DeviceScanActivity extends ListActivity {
   

    private BluetoothAdapter bluetoothAdapter;
    private boolean mScanning;
    private Handler handler;

    // Stops scanning after 10 seconds.
    private static final long SCAN_PERIOD = 10000;
    ...
    private void scanLeDevice(final boolean enable) {
   
        if (enable) {
   
            // Stops scanning after a pre-defined scan period.
            handler.postDelayed(new Runnable() {
   
                @Override
                public void run() {
   
                    mScanning = false;
                    bluetoothAdapter.stopLeScan(leScanCallback);
                }
            }, SCAN_PERIOD);

            mScanning = true;
            bluetoothAdapter.startLeScan(leScanCallback);
        } else {
   
            mScanning = false;
            bluetoothAdapter.stopLeScan(leScanCallback);
        }
        ...
    }
...
}

Note: The BluetoothLeScanner is only available from the BluetoothAdapter if Bluetooth is currently enabled on the device. If Bluetooth is not enabled, then getBluetoothLeScanner() returns null.

以下代码示例是 ScanCallback 的实现,它是用于传递 BLE 扫描结果的接口。找到结果后,会将它们添加到 DeviceScanActivity 中的列表适配器中以显示给用户。

private LeDeviceListAdapter leDeviceListAdapter = new LeDeviceListAdapter();

// Device scan callback.
private ScanCallback leScanCallback =
        new ScanCallback() {
   
            @Override
            public void onScanResult(int callbackType, ScanResult result) {
   
                super.onScanResult(callbackType, result);
                leDeviceListAdapter.addDevice(result.getDevice());
                leDeviceListAdapter.notifyDataSetChanged();
            }
        };

Note: You can only scan for Bluetooth LE devices or scan for classic Bluetooth devices, as described in Bluetooth overview. You cannot scan for both Bluetooth LE and classic devices at the same time.

连接设备上的 GATT 服务器

绑定服务

在本例中,提供一个 Activity (DeviceControlActivity) 来连接、显示设备及服务数据。真正通过 API 与 BLE 设备交互的是名为 BluetoothLeService 的 Service:

class BluetoothLeService extends Service {
   

    private Binder binder = new LocalBinder();

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
   
        return binder;
    }

    class LocalBinder extends Binder {
   
        public BluetoothLeService getService() {
   
            return BluetoothLeService.this;
        }
    }
}
class DeviceControlActivity extends AppCompatActivity {
   

    private BluetoothLeService bluetoothService;

    private ServiceConnection serviceConnection = new ServiceConnection() {
   
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
   
            bluetoothService = ((LocalBinder) service).getService();
            if (bluetoothService != null) {
   
                // call functions on service to check connection and connect to devices
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
   
            bluetoothService = null;
        }
    };

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
   
        super.onCreate(savedInstanceState);
        setContentView(R.layout.gatt_services_characteristics);

        Intent gattServiceIntent = new Intent(this, BluetoothLeService.class)
  • 6
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值