Android Things是谷歌推出的面向物联网设备的Android系统变体,它让开发者可以直接在开发板上使用熟悉的Android API控制硬件外设,并借助成熟的网络栈接入云端。对于想验证智能硬件想法的团队来说,用开发板跑通一个传感采集加远程控制的闭环,比从零写嵌入式固件要高效得多。

开发板选型与系统镜像烧录
在动手写代码前,第一步是确认手里的开发板是否在Android Things的官方支持列表内。早期支持的NXP Pico i.MX7D、Raspberry Pi 3等型号都有对应的系统镜像,而后续新出的板子往往没有官方适配。如果强行刷入不兼容的镜像,开发板可能卡在启动logo或者外设节点缺失。因此选型阶段就要去查阅兼容矩阵,优先选择社区资料丰富的型号,这样后面排查驱动问题会轻松不少。
烧录过程本身并不复杂,官方提供了Android Things Setup Utility,也可以手动使用dd命令或者Etcher将img写入SD卡。以树莓派为例,把下载好的压缩包解压出img文件,用工具写入存储卡后插入板子,接上HDMI就能看到初始配置界面。首次启动需要连Wi-Fi并绑定谷歌账号,这一步实际上是在注册设备到谷歌的云端控制台,方便后续推送OTA更新。要注意的是,部分区域网络访问谷歌服务不稳定,可以提前准备离线绑定方案或者改用本地代理。
系统起来之后,建议先通过adb连接确认板子状态。在电脑端执行adb devices应当能看到对应序列号,再跑adb shell getprop ro.product.model验证系统标识。只有adb能稳定连上,后面的应用安装和日志抓取才方便。很多新手卡在adb授权弹窗不显示,其实是HDMI没接或者默认输入法抢占焦点,接好屏幕点允许即可。
使用Android API操作GPIO与I2C外设
Android Things最大的便利是提供了PeripheralManager来管理GPIO、I2C、SPI等总线,开发者不再需要交叉编译C库。以点亮一个接在GPIO口的LED为例,先要在AndroidManifest里声明权限,然后拿到Gpio对象设置方向和电平。下面这段Java代码演示了如何每隔一秒翻转一次引脚状态:
import com.google.android.things.pio.Gpio;
import com.google.android.things.pio.PeripheralManager;
import java.io.IOException;
public class LedBlink {
private static final String PIN_NAME = "BCM6"; // 树莓派物理引脚对应名
private Gpio ledGpio;
public void start() throws IOException {
PeripheralManager manager = PeripheralManager.getInstance();
ledGpio = manager.openGpio(PIN_NAME);
ledGpio.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW);
boolean on = false;
while (true) {
ledGpio.setValue(on);
on = !on;
try { Thread.sleep(1000); } catch (InterruptedException e) {}
}
}
public void stop() throws IOException {
if (ledGpio != null) {
ledGpio.close();
}
}
}
上面代码里的PIN_NAME必须和开发板引脚映射表一致,写错会导致打开失败并抛出IOException。相比直接写Linux sysfs节点,这种API屏蔽了路径差异,换板子时只需改字符串。但也要注意,Android Things的用户态API在高频读写时延迟比内核驱动大,做精密时序的传感器最好选I2C或SPI硬件协议。
对于温湿度传感器这类I2C设备,流程类似:通过manager.openI2cDevice获取对象,再用readRegByte、writeRegByte读写寄存器。下面的片段展示从地址0x44的设备读取两个字节:
import com.google.android.things.pio.I2cDevice;
import com.google.android.things.pio.PeripheralManager;
import java.io.IOException;
public class SensorRead {
public int readRaw() throws IOException {
PeripheralManager pm = PeripheralManager.getInstance();
I2cDevice device = pm.openI2cDevice("I2C1", 0x44);
byte[] buf = new byte[2];
device.readRegBuffer(0x00, buf, buf.length);
device.close();
return ((buf[0] & 0xFF) << 8) | (buf[1] & 0xFF);
}
}
实际项目中应当把设备打开和关闭放在生命周期方法里,避免应用退到后台后资源泄漏。另外I2C地址冲突是常见问题,一块板子挂多个从机时要核对原理图,必要时用多路复用器扩展总线。
通过MQTT将设备数据接入物联网平台
外设数据采到之后,下一步是送到云端做展示或分析。MQTT由于报文小、适合不稳定网络,是物联网里最常用的协议。在Android Things上可以用Eclipse Paho客户端,它本身就是为Android设计的,集成很方便。核心逻辑是建一个MqttAndroidClient,连到 broker 后定时publish消息。
import org.eclipse.paho.android.service.MqttAndroidClient;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import android.content.Context;
public class MqttPublisher {
public void publish(Context ctx, String payload) throws Exception {
String serverUri = "tcp://192.168.0.1:1883";
MqttAndroidClient client = new MqttAndroidClient(ctx, serverUri, "things01");
MqttConnectOptions opt = new MqttConnectOptions();
opt.setAutomaticReconnect(true);
client.connect(opt).waitForCompletion();
MqttMessage msg = new MqttMessage(payload.getBytes());
msg.setQos(1);
client.publish("sensor/room1", msg);
client.disconnect();
}
}
这里broker地址用了内网192.168.0.1,在原型阶段完全可以跑一个本地Mosquitto来验证。setAutomaticReconnect能在Wi-Fi抖动时自动重连,对开发板环境很实用。Qos设为1代表至少送达一次,不会像Qos0那样丢数据,也不会像Qos2那样握手太重。
当数据上了云,反向控制也常通过订阅主题实现。比如手机App发一条开灯指令到cmd/led,板子端在messageArrived回调里解析并调用前面写的Gpio翻转。需要留意的是,Android Things默认后台限制比手机松,但长连接仍可能被系统回收,最好用ForegroundService保活,并在Manifest里声明对应服务与网络权限。整套链路跑通后,你就拥有了一个用Android Things开发板搭起来的最小物联网原型。
常见误区与工程化建议
不少团队把Android Things当成普通手机系统来写UI,结果浪费大量空间在SurfaceFlinger上。其实无屏设备应当用headless模式,去掉界面组件,专注后台服务与硬件访问。另一个误区是忽视SELinux策略,直接openGpio报权限拒绝时,很多人以为是代码错,其实是厂商镜像没开放该节点,需要换支持列表里的引脚。
工程化方面,建议把外设操作封装成独立模块,通过接口暴露给业务逻辑,这样换传感器型号时只改实现类。构建上用Gradle同一套依赖管理,把Paho、Thing驱动包统一版本。最后留好日志通道,用Logcat或者本地文件缓冲,方便现场排查。把这些习惯带入早期原型,后续转产才不会推倒重来。
Android_Things物联网IoT开发板修改时间:2026-08-15 16:48:39