App Inventor 2 蓝牙遥控教程

覆盖经典蓝牙SPP连接全流程,重点解决高版本安卓(Android 12+)权限问题。

一、蓝牙类型选择

类型组件适用场景
经典蓝牙(SPP)蓝牙客户端蓝牙模块(HC-05/06、JDY-34)、蓝牙打印机
低功耗蓝牙(BLE)BluetoothLE扩展智能手环、传感器、BLE模块
遥控小车/Arduino → 用经典蓝牙SPP(本文重点)

二、⚠️ 高版本安卓权限问题(必读)

Android 12(API 31)起,蓝牙权限发生重大变化:
安卓版本需要的权限
Android 11 及以下ACCESS_FINE_LOCATION
Android 12+BLUETOOTH_SCAN + BLUETOOTH_CONNECT
症状:高版本安卓扫描不到蓝牙设备,或连接时崩溃。 解决方案
// 在 Screen1.初始化 时请求权限
当 Screen1.初始化 时
  // 请求蓝牙相关权限(Android 12+)
  调用 权限请求1.请求权限("android.permission.BLUETOOTH_SCAN")
  调用 权限请求1.请求权限("android.permission.BLUETOOTH_CONNECT")
  // Android 11及以下还需要位置权限
  调用 权限请求1.请求权限("android.permission.ACCESS_FINE_LOCATION")
注意:App Inventor 2 中文网版本(fun123.cn)已内置权限处理,MIT官方版本需手动添加。

三、经典蓝牙连接流程

3.1 准备工作

  1. 手机系统设置 → 蓝牙,搜索并配对蓝牙模块(如HC-05,默认密码1234或0000)
  2. 配对成功后,才能在App中看到该设备

3.2 界面设计

  • 列表选择器:选择蓝牙设备
  • 标签:显示连接状态
  • 按钮:断开连接
  • 蓝牙客户端组件(不可见)

3.3 连接代码块

// 打开设备列表
当 列表选择器_蓝牙.准备选择 时
  设置 列表选择器_蓝牙.元素 = 蓝牙客户端1.已配对设备地址列表

// 选择设备后连接
当 列表选择器_蓝牙.完成选择 时(选择项, 选择索引)
  如果 蓝牙客户端1.连接(选择项) 则
    设置 标签_状态.文本 = "✅ 已连接:" + 选择项
    设置 按钮_断开.启用 = 真
  否则
    调用 对话框1.显示消息对话框("连接失败,请重试", "提示", "确定")

// 断开连接
当 按钮_断开.被点击 时
  调用 蓝牙客户端1.断开连接
  设置 标签_状态.文本 = "❌ 未连接"
  设置 按钮_断开.启用 = 假

四、发送控制指令

4.1 发送文本指令

// 发送字符串(如"F"=前进,"B"=后退)
当 按钮_前进.被点击 时
  如果 蓝牙客户端1.已连接 则
    调用 蓝牙客户端1.发送文本("F")
  否则
    调用 对话框1.显示消息对话框("请先连接蓝牙", "提示", "确定")

当 按钮_后退.被点击 时
  如果 蓝牙客户端1.已连接 则
    调用 蓝牙客户端1.发送文本("B")

当 按钮_左转.被点击 时
  如果 蓝牙客户端1.已连接 则
    调用 蓝牙客户端1.发送文本("L")

当 按钮_右转.被点击 时
  如果 蓝牙客户端1.已连接 则
    调用 蓝牙客户端1.发送文本("R")

当 按钮_停止.被点击 时
  如果 蓝牙客户端1.已连接 则
    调用 蓝牙客户端1.发送文本("S")

4.2 发送数字指令(带换行符)

Arduino通常用 Serial.readStringUntil('\n') 读取,需要加换行符:
定义 发送指令(指令)
  如果 蓝牙客户端1.已连接 则
    调用 蓝牙客户端1.发送文本(合并字符串(指令, "\n"))

4.3 发送速度值(滑动条控制)

当 滑动条_速度.位置改变 时(滑块位置)
  初始化局部变量 速度 = 四舍五入(滑块位置)
  设置 标签_速度.文本 = 合并字符串("速度:", 速度)
  如果 蓝牙客户端1.已连接 则
    调用 蓝牙客户端1.发送文本(合并字符串("V", 速度, "\n"))

五、接收蓝牙数据

5.1 用计时器轮询接收

// 计时器间隔设为100ms
当 计时器1.计时 时
  如果 蓝牙客户端1.已连接 且 蓝牙客户端1.可用字节数 > 0 则
    初始化局部变量 数据 = 蓝牙客户端1.接收文本(蓝牙客户端1.可用字节数)
    设置 标签_接收.文本 = 合并字符串("收到:", 数据)

5.2 接收固定长度数据

当 计时器1.计时 时
  如果 蓝牙客户端1.已连接 且 蓝牙客户端1.可用字节数 >= 4 则
    // 接收4个字节
    初始化局部变量 数据 = 蓝牙客户端1.接收文本(4)
    调用 处理数据(数据)

六、完整案例:蓝牙遥控小车

6.1 界面设计

┌─────────────────────────────────┐
│  蓝牙遥控小车                    │
│  [选择设备]  状态:未连接         │
├─────────────────────────────────┤
│           [  前进  ]             │
│  [左转]   [  停止  ]   [右转]    │
│           [  后退  ]             │
├─────────────────────────────────┤
│  速度:50  [━━━━●━━━━━━━━━━]    │
├─────────────────────────────────┤
│  接收数据:                      │
└─────────────────────────────────┘

6.2 完整代码块

初始化全局变量 当前速度 = 50

当 Screen1.初始化 时
  设置 滑动条_速度.最小值 = 0
  设置 滑动条_速度.最大值 = 100
  设置 滑动条_速度.滑块位置 = 50
  设置 计时器1.计时间隔 = 100
  设置 计时器1.启用计时 = 真

// 连接蓝牙
当 列表选择器_蓝牙.准备选择 时
  设置 列表选择器_蓝牙.元素 = 蓝牙客户端1.已配对设备地址列表

当 列表选择器_蓝牙.完成选择 时(选择项, 选择索引)
  如果 蓝牙客户端1.连接(选择项) 则
    设置 标签_状态.文本 = "✅ 已连接"
    设置 标签_状态.背景颜色 = 绿色

// 方向控制
当 按钮_前进.被点击 时
  调用 发送(合并字符串("F", 全局变量 当前速度))
当 按钮_后退.被点击 时
  调用 发送(合并字符串("B", 全局变量 当前速度))
当 按钮_左转.被点击 时
  调用 发送("L")
当 按钮_右转.被点击 时
  调用 发送("R")
当 按钮_停止.被点击 时
  调用 发送("S")

// 速度控制
当 滑动条_速度.位置改变 时(滑块位置)
  设置 全局变量 当前速度 = 四舍五入(滑块位置)
  设置 标签_速度.文本 = 合并字符串("速度:", 全局变量 当前速度)

// 发送过程
定义 发送(指令)
  如果 蓝牙客户端1.已连接 则
    调用 蓝牙客户端1.发送文本(合并字符串(指令, "\n"))

// 接收数据
当 计时器1.计时 时
  如果 蓝牙客户端1.已连接 且 蓝牙客户端1.可用字节数 > 0 则
    设置 标签_接收.文本 = 蓝牙客户端1.接收文本(蓝牙客户端1.可用字节数)

6.3 Arduino端代码参考

#include <SoftwareSerial.h>
SoftwareSerial BT(10, 11); // RX, TX

int speed = 50;

void setup() {
  BT.begin(9600);
  // 初始化电机引脚...
}

void loop() {
  if (BT.available()) {
    String cmd = BT.readStringUntil('\n');
    cmd.trim();
    
    if (cmd.startsWith("F")) {
      speed = cmd.substring(1).toInt();
      // 前进...
    } else if (cmd == "B") {
      // 后退...
    } else if (cmd == "L") {
      // 左转...
    } else if (cmd == "R") {
      // 右转...
    } else if (cmd == "S") {
      // 停止...
    }
  }
}

七、常见问题

Q1:设备列表为空?

  • 确认已在手机系统设置中配对蓝牙设备
  • Android 12+ 需要授予蓝牙权限
  • 检查蓝牙模块是否已上电

Q2:连接成功但发送无响应?

  • 检查波特率是否匹配(HC-05默认9600)
  • 检查指令格式(是否需要换行符\n
  • 用串口助手App验证蓝牙模块是否正常

Q3:Android 12+ 连接崩溃?

Screen1.初始化 中添加权限请求(见第二节)。

Q4:JDY-34双模蓝牙怎么用?

JDY-34支持BLE和SPP双模,默认SPP模式,用法与HC-05相同。切换到BLE模式需要AT指令配置。

参考资料


文档版本:2026.03 | 作者:App Inventor 2 中文网 www.fun123.cn

参考资料与版权声明

原文来源

版权声明

本文档基于 MIT App Inventor 官方文档及社区资源整理,版权归原作者所有:
  • MIT App Inventor 官方文档采用 CC BY-SA 4.0 授权
  • MIT App Inventor Community 帖子版权归原作者所有
本文档由 ai2claw 🐝 整理,仅供学习参考,如有侵权请联系删除。