You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

利用NFC标签建立Android手机与Raspberry Pi的BLE连接

嘿,这个跨设备联动的场景挺实用的!我之前做过类似的项目,给你一步步拆解实现步骤,保证能跑通:

一、NFC标签写入与读取(获取RPi的MAC地址)

首先得把树莓派的BLE MAC地址写入NFC标签,推荐用NDEF格式,方便Android直接解析:

  • 写入标签:可以用现成的NFC工具APP(比如NFC Tools),选择「文本记录」,输入树莓派的BLE MAC地址(格式要严格遵循AA:BB:CC:DD:EE:FF),写入到标签中。
  • Android端读取NFC:在你的Activity里注册NFC过滤逻辑,捕获NDEF_DISCOVERED intent并解析MAC地址:
override fun onNewIntent(intent: Intent?) {
    super.onNewIntent(intent)
    if (NfcAdapter.ACTION_NDEF_DISCOVERED == intent?.action) {
        val rawMessages = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES)
        rawMessages?.let { messages ->
            val ndefMessage = messages[0] as NdefMessage
            val record = ndefMessage.records[0]
            val piMacAddress = String(record.payload, Charsets.UTF_8).trim()
            // 拿到MAC地址后直接触发BLE连接逻辑
            connectToPiViaBle(piMacAddress)
        }
    }
}

注意:别忘了在AndroidManifest里添加NFC权限和intent filter,确保APP能捕获NFC触发的事件

二、Android端BLE连接核心实现

BLE连接需要处理权限、适配器初始化、连接回调这几个关键环节:

  1. 权限配置(AndroidManifest.xml):
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <!-- Android 6+必须,否则无法扫描BLE设备 -->
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />
<!-- Android 12+ 额外需要以下权限 -->
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
  1. 初始化蓝牙适配器并发起连接:
private fun connectToPiViaBle(macAddress: String) {
    val bluetoothManager = getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
    val bluetoothAdapter = bluetoothManager.adapter
    
    // 检查蓝牙是否开启,未开启则引导用户打开
    if (!bluetoothAdapter.isEnabled) {
        val enableBtIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
        startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT)
        return
    }
    
    // 获取树莓派的BLE设备实例
    val piDevice = bluetoothAdapter.getRemoteDevice(macAddress)
    // 定义BLE连接回调,处理连接状态和服务发现
    val gattCallback = object : BluetoothGattCallback() {
        override fun onConnectionStateChange(gatt: BluetoothGatt?, status: Int, newState: Int) {
            super.onConnectionStateChange(gatt, status, newState)
            when (newState) {
                BluetoothProfile.STATE_CONNECTED -> {
                    runOnUiThread { Toast.makeText(this@MainActivity, "已连接到树莓派", Toast.LENGTH_SHORT).show() }
                    gatt?.discoverServices() // 连接成功后立即发现服务,用于后续通信
                }
                BluetoothProfile.STATE_DISCONNECTED -> {
                    runOnUiThread { Toast.makeText(this@MainActivity, "连接已断开", Toast.LENGTH_SHORT).show() }
                }
            }
        }
        
        override fun onServicesDiscovered(gatt: BluetoothGatt?, status: Int) {
            super.onServicesDiscovered(gatt, status)
            if (status == BluetoothGatt.GATT_SUCCESS) {
                // 找到树莓派上定义的BLE服务和特征,发送播放指令
                val playService = gatt?.getService(UUID.fromString("你的自定义服务UUID"))
                val playCharacteristic = playService?.getCharacteristic(UUID.fromString("你的自定义特征UUID"))
                playCharacteristic?.value = "play_video:demo.mp4".toByteArray()
                gatt?.writeCharacteristic(playCharacteristic)
            }
        }
    }
    
    // 发起BLE连接(第三个参数为false表示不自动重连,可根据需求调整)
    piDevice.connectGatt(this, false, gattCallback)
}
三、树莓派端BLE服务配置

树莓派这边用BlueZ工具链实现BLE外围设备,步骤如下:

  1. 安装BlueZ依赖:
sudo apt-get update
sudo apt-get install bluez bluez-tools python3-pip
pip3 install bluepy
  1. 编写BLE服务脚本(用bluepy库实现):
from bluepy.btle import Peripheral, UUID, Characteristic, Service, Advertiser
import subprocess

# 自定义服务和特征的UUID(可以在线生成随机UUID)
SERVICE_UUID = UUID("12345678-1234-5678-1234-567812345678")
PLAY_CHAR_UUID = UUID("87654321-4321-8765-4321-876543218765")

class VideoPlayService(Service):
    def __init__(self, peripheral):
        super().__init__(peripheral, SERVICE_UUID, True)
        self.addCharacteristic(VideoPlayCharacteristic(self))

class VideoPlayCharacteristic(Characteristic):
    def __init__(self, service):
        super().__init__(service, PLAY_CHAR_UUID, Characteristic.PROP_WRITE)
    
    def writeValue(self, value, offset):
        # 解析Android端发送的指令
        command = value.decode('utf-8')
        if command.startswith("play_video:"):
            video_path = command.split(":")[1]
            # 调用omxplayer播放视频到HDMI接口(电视)
            subprocess.run(["omxplayer", "-o", "hdmi", f"/home/pi/videos/{video_path}"])

# 启动BLE外围设备
peripheral = Peripheral()
peripheral.addService(VideoPlayService(peripheral))
peripheral.setAdvertiseData(Advertiser(name="PiVideoPlayer"))
peripheral.startAdvertising()

try:
    print("等待Android端连接...")
    while True:
        peripheral.waitForNotifications(1.0)
except KeyboardInterrupt:
    peripheral.stopAdvertising()
    print("服务已停止")
  1. 配置树莓派蓝牙状态:
sudo bluetoothctl
power on
discoverable on
pairable on
exit
四、关键注意事项与故障排查
  • MAC地址格式:必须严格遵循XX:XX:XX:XX:XX:XX格式,大小写不影响,但Android的getRemoteDevice方法会校验格式。
  • BLE连接稳定性:如果连接频繁断开,检查树莓派的蓝牙信号强度,或在Android端添加重连逻辑。
  • 权限问题:Android端一定要在运行时申请位置权限(6+)和蓝牙相关权限(12+),否则无法扫描或连接BLE设备。
  • 树莓派服务启动:确保BlueZ服务正常运行,用sudo systemctl status bluetooth查看状态,异常则重启服务sudo systemctl restart bluetooth。

内容的提问来源于stack exchange,提问作者Xflkekw

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 03:38:48