【OpenHarmony/HarmonyOs 】CheckMe 传感器与触觉反馈实践:加速度计、光线传感器、距离传感器和振动检测
【OpenHarmony/HarmonyOs 】CheckMe 传感器与触觉反馈实践:加速度计、光线传感器、距离传感器和振动检测
本文基于
CheckMe项目,聚焦 HarmonyOS 设备感知能力:传感器、音频采集播放、振动马达与硬件检测交互。这个方向和前面的权限、服务卡片、端侧 AI、实况窗等文章不重复,更适合写“鸿蒙设备能力实战”。
HarmonyOS 的全场景能力不只是跨设备,也包括对设备硬件的细粒度调用。一个真正像样的设备检测工具,不能只显示 CPU 和内存,还应该能检测:
- 扬声器是否正常
- 麦克风是否有输入
- 振动马达是否可用
- 加速度计是否有数据
- 陀螺仪是否正常
- 光线传感器是否工作
- 距离传感器是否响应
CheckMe 的硬件检测页就围绕这些能力做了比较完整的工程组织。🎛️
一、硬件检测页的设计目标
硬件检测不是简单调用 API,它要解决三个问题:
- 让用户知道正在检测什么。
- 让用户能感知检测过程。
- 检测失败时给出明确状态,而不是静默无响应。
因此项目中定义了统一的测试状态:
enum TestStatus {
NOT_STARTED = 'not_started',
TESTING = 'testing',
PASSED = 'passed',
FAILED = 'failed',
UNAVAILABLE = 'unavailable'
}
这套状态可以覆盖大多数硬件检测场景:
TESTING:正在监听、播放、定位或采集PASSED:检测通过FAILED:能力存在但结果异常UNAVAILABLE:设备不支持或 API 不可用
统一状态模型让页面 UI、Toast 提示、检测结果列表都能复用同一套逻辑。
二、扬声器测试:用 AudioRenderer 播放正弦波
在 HardwareTest.ets 中,扬声器测试使用 AudioRenderer 播放 PCM 数据。核心代码如下:
const audioStreamInfo: audio.AudioStreamInfo = {
samplingRate: audio.AudioSamplingRate.SAMPLE_RATE_44100,
channels: audio.AudioChannel.CHANNEL_2,
encodingType: audio.AudioEncodingType.ENCODING_TYPE_RAW,
sampleFormat: audio.AudioSampleFormat.SAMPLE_FORMAT_S16LE
};
const audioRendererOptions: audio.AudioRendererOptions = {
streamInfo: audioStreamInfo,
rendererInfo: {
usage: audio.StreamUsage.STREAM_USAGE_MUSIC,
rendererFlags: 0
}
};
this.audioRenderer = await audio.createAudioRenderer(audioRendererOptions);
await this.audioRenderer.start();
项目没有依赖外部音频文件,而是直接生成正弦波:
const sampleRate = 44100;
const durationSec = 2;
const numSamples = sampleRate * durationSec;
const buffer: ArrayBuffer = new ArrayBuffer(numSamples * 2);
const view = new Int16Array(buffer);
for (let i = 0; i < numSamples; i++) {
const t = i / sampleRate;
const sample = Math.sin(2 * Math.PI * this.speakerFrequency * t) * 8000;
view[i] = Math.max(-32768, Math.min(32767, Math.round(sample)));
}
这样做有几个优点:
- 不需要打包音频资源
- 可以动态调整频率
- 可以测试左右声道
- 更适合硬件检测场景
📌 对设备检测工具来说,生成测试信号比播放固定音频更灵活。
三、麦克风测试:用 AudioCapturer 实时读取音量
麦克风检测使用 AudioCapturer:
const audioCapturerOptions: audio.AudioCapturerOptions = {
streamInfo: {
samplingRate: audio.AudioSamplingRate.SAMPLE_RATE_44100,
channels: audio.AudioChannel.CHANNEL_1,
encodingType: audio.AudioEncodingType.ENCODING_TYPE_RAW,
sampleFormat: audio.AudioSampleFormat.SAMPLE_FORMAT_S16LE
},
capturerInfo: {
source: audio.SourceType.SOURCE_TYPE_MIC,
capturerFlags: 0
}
};
this.audioCapturer = await audio.createAudioCapturer(audioCapturerOptions);
await this.audioCapturer.start();
然后循环读取音频数据,计算平均音量:
const buffer: ArrayBuffer = await this.audioCapturer.read(bufferSize, true);
const view = new Int16Array(buffer);
let sum = 0;
for (let i = 0; i < view.length; i++) {
sum = sum + Math.abs(view[i]);
}
const avg = sum / view.length;
this.micVolume = Math.min(100, Math.round(avg / 327.68));
这段代码把底层 PCM 数据转换成用户能理解的“音量百分比”。如果 micVolume > 5,就认为检测到声音:
if (this.micVolume > 5) {
this.updateResult('麦克风测试', TestStatus.PASSED, '检测到声音');
} else {
this.updateResult('麦克风测试', TestStatus.FAILED, '未检测到声音');
}
这比简单“能否打开麦克风”更有意义,因为它真的检测了输入数据。
四、振动检测:先判断支持,再触发触觉反馈
振动马达检测使用 @ohos.vibrator:
private async startVibratorTest(): Promise<void> {
this.vibratorTesting = true;
this.updateResult('振动马达', TestStatus.TESTING, '振动中...');
const isSupported: boolean = vibrator.isHdHapticSupported();
if (!isSupported) {
this.updateResult('振动马达', TestStatus.UNAVAILABLE, '设备不支持振动');
this.vibratorTesting = false;
return;
}
const vibrateTime: vibrator.VibrateTime = {
type: 'time',
duration: 500
};
const vibrateAttr: vibrator.VibrateAttribute = {
usage: 'touch'
};
await vibrator.startVibration(vibrateTime, vibrateAttr);
}
这里的顺序很关键:
- 先设置测试状态。
- 再判断设备是否支持。
- 支持才触发振动。
- 不支持时返回
UNAVAILABLE。
这种写法比直接调用 startVibration() 更稳,因为不同设备形态对振动支持情况可能不同。
五、加速度计:实时监听三轴数据
加速度计检测使用 Sensor API 监听三轴数据:
sensor.on(
sensor.SensorType.SENSOR_TYPE_ID_ACCELEROMETER,
(data: sensor.AccelerometerResponse) => {
this.sensorAccelerometer = {
x: Math.round(data.x * 100) / 100,
y: Math.round(data.y * 100) / 100,
z: Math.round(data.z * 100) / 100
};
this.updateResult(
'加速度计',
TestStatus.PASSED,
'X:' + this.sensorAccelerometer.x.toFixed(2) +
' Y:' + this.sensorAccelerometer.y.toFixed(2) +
' Z:' + this.sensorAccelerometer.z.toFixed(2) + ' m/s²'
);
},
{ interval: 100000000 }
);
用户移动设备时,三轴数据会变化。页面就能给出“监听中”“检测通过”“无数据”等状态。
停止时要记得注销监听:
sensor.off(sensor.SensorType.SENSOR_TYPE_ID_ACCELEROMETER);
传感器类能力一定要注意释放,否则页面切换后仍然监听,会造成不必要的资源消耗。
六、陀螺仪:检测旋转角速度
陀螺仪和加速度计类似,但它检测的是旋转角速度:
sensor.on(
sensor.SensorType.SENSOR_TYPE_ID_GYROSCOPE,
(data: sensor.GyroscopeResponse) => {
this.sensorGyroscope = {
x: Math.round(data.x * 100) / 100,
y: Math.round(data.y * 100) / 100,
z: Math.round(data.z * 100) / 100
};
this.updateResult(
'陀螺仪',
TestStatus.PASSED,
'X:' + this.sensorGyroscope.x.toFixed(2) +
' Y:' + this.sensorGyroscope.y.toFixed(2) +
' Z:' + this.sensorGyroscope.z.toFixed(2) + ' rad/s'
);
},
{ interval: 100000000 }
);
它适合检测:
- 设备旋转
- 姿态变化
- 横竖屏辅助判断
- 游戏和运动场景输入
在 CheckMe 中,它作为硬件检测项出现,用户旋转设备即可看到数据变化。
七、光线传感器:让“沉浸光感”有真实硬件依据
光线传感器检测代码:
sensor.on(sensor.SensorId.AMBIENT_LIGHT, (data: sensor.LightResponse) => {
this.sensorLight = Math.round(data.intensity * 100) / 100;
this.updateResult(
'光线传感器',
TestStatus.PASSED,
'强度: ' + this.sensorLight.toFixed(1) + ' lux'
);
}, { interval: 500000000 });
光线传感器返回的是环境光强度,单位常用 lux。
这类数据除了做硬件检测,还可以扩展为:
- 根据环境光调整图表亮度
- 弱光环境自动降低页面对比度
- 强光环境提高关键文字可读性
- 结合深色模式做更自然的视觉体验
这就把“沉浸光感”从 UI 风格变成了硬件能力驱动。
八、距离传感器:检测贴近状态
距离传感器代码:
sensor.on(sensor.SensorId.PROXIMITY, (data: sensor.ProximityResponse) => {
this.sensorProximity = data.distance;
this.updateResult(
'距离传感器',
TestStatus.PASSED,
'距离: ' + this.sensorProximity.toFixed(2) + ' cm'
);
}, { interval: 500000000 });
距离传感器可以用于:
- 通话贴耳检测
- 防误触
- 口袋模式
- 设备状态判断
在工具类应用中,它可以作为硬件自检项,帮助用户确认传感器是否工作正常。
九、硬件检测的资源释放策略
项目中切换模块时会停止上一个模块的资源:
private switchModule(module: TestModule): void {
if (this.currentModule === TestModule.SPEAKER) {
this.stopSpeakerTest();
} else if (this.currentModule === TestModule.MICROPHONE) {
this.stopMicrophoneTest();
} else if (this.currentModule === TestModule.SENSOR) {
this.stopSensorTests();
} else if (this.currentModule === TestModule.GPS) {
this.stopGpsTest();
}
this.currentModule = module;
this.isFullScreen = false;
}
这是硬件类功能非常重要的工程习惯:
- 音频播放要 release
- 麦克风采集要 stop
- 传感器监听要 off
- 振动要 stop
- 定位要停止或避免重复请求
否则应用可能出现耗电、占用硬件资源、页面切走后仍有回调等问题。
十、文章小结
CheckMe 的硬件检测页把 HarmonyOS 设备能力串成了一套完整体验:
AudioRenderer:扬声器测试AudioCapturer:麦克风测试vibrator:触觉反馈检测sensor:加速度计、陀螺仪、光线、距离传感器- 统一
TestStatus:管理检测状态 - 资源释放:保证切换模块后不残留监听
这类文章很适合突出 HarmonyOS 的系统能力,因为它不是单纯 UI 页面,而是真正调用了设备硬件。
最后一句总结:硬件检测工具的价值,不只是告诉用户“设备有什么”,而是让用户真实感知“设备能力是否可用”。 🔧
参考资料
- 华为开发者文档:Sensor Overview
- 华为开发者文档:Audio Kit
- 华为开发者文档:AudioCapturer API


更多推荐




所有评论(0)