如何在Android Wear OS上保存传输智能手表传感器数据并导出为CSV
实现优化与问题解决方案
现有实现的已知问题
你当前的代码有几个直接影响写入可靠性的问题:
- 直接使用相对路径
data.csv,Wear OS基于Android系统,相对路径默认指向应用私有目录的根路径,后续你查找文件时会无法定位路径 - 缺少数据分隔符与时间戳:所有PPG数值会连续写入无换行,最终得到的CSV文件无法正确拆分;同时PPG数据必须匹配采样时间戳才能用于后续信号分析,仅存数值没有实用价值
- 未做缓冲区刷新与资源释放:
FileWriter默认带缓冲区,你仅调用write()方法不会立即落盘,应用退后台、崩溃时会丢失大量数据;且onResume中初始化的writer没有在onPause等生命周期回调中关闭,会出现资源泄漏 - 主线程执行IO操作:
onSensorChanged运行在主线程,PPG采样频率通常在25~100Hz,频繁IO操作会阻塞主线程导致界面卡顿甚至应用崩溃
存储位置选择
优先选择手表本地应用私有目录存储:
- 不需要额外申请存储权限,写入速度快,不会因为蓝牙连接不稳定丢失数据
- 如果需要实时同步到手机,可采用Wear OS提供的
Wearable Data LayerAPI批量同步数据,避免高频传输带来的功耗损耗
写入逻辑优化方案
1. 基础逻辑调整
- 写入路径显式指定为应用私有目录:
new FileWriter(new File(getFilesDir(), "data.csv"), true) - 每行数据增加时间戳与换行符:写入格式改为
System.currentTimeMillis() + "," + sensorData + "\n" - 生命周期匹配:在
onPause回调中添加writer.flush()+writer.close()逻辑,确保退出时所有缓冲区数据落盘 - 异步写入:用
ConcurrentLinkedQueue缓存传感器数据,启动单独的后台线程批量写入文件,避免阻塞主线程
2. 优化后代码示例
首先在MainActivity中新增成员变量:
private ConcurrentLinkedQueue<String> dataQueue = new ConcurrentLinkedQueue<>(); private ExecutorService writeExecutor = Executors.newSingleThreadExecutor(); private volatile boolean isWriting = true; private FileWriter writer;
修改onResume初始化逻辑:
@Override protected void onResume() { super.onResume(); isWriting = true; try { // 显式指定存储路径 File csvFile = new File(getFilesDir(), "data.csv"); writer = new FileWriter(csvFile, true); // 启动后台写入线程 writeExecutor.execute(() -> { while (isWriting) { String data = dataQueue.poll(); if (data != null) { try { writer.write(data); // 每满10条刷一次缓冲区,可根据采样频率调整 if (dataQueue.size() % 10 == 0) { writer.flush(); } } catch (IOException e) { e.printStackTrace(); } } else { // 队列为空时休眠10ms降低CPU占用 try { Thread.sleep(10); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } } // 退出循环后刷入剩余数据并关闭写入器 try { writer.flush(); writer.close(); } catch (IOException e) { e.printStackTrace(); } }); } catch (IOException e) { e.printStackTrace(); } }
修改onSensorChanged逻辑,仅把数据推入队列:
@Override public void onSensorChanged(SensorEvent event) { if (event.sensor.getType() == 65572) { float sensorData = event.values[0]; String dataString = System.currentTimeMillis() + "," + sensorData + "\n"; textView.setText(Float.toString(sensorData)); dataQueue.offer(dataString); } }
添加onPause销毁逻辑:
@Override protected void onPause() { super.onPause(); isWriting = false; writeExecutor.shutdown(); }
CSV文件导出到PC的方法
方法1:ADB直接拉取(开发调试阶段最方便)
- 手表开启开发者选项与USB调试,通过USB连接电脑,或者使用无线ADB连接
- 执行命令直接拉取文件:
adb pull /data/data/[你的应用包名]/files/data.csv ./local_data.csv
拉取到本地的CSV文件可直接导入MATLAB做信号分析。
方法2:用户端可视化导出
在应用内添加导出按钮,点击后触发:
- 将CSV文件通过
Wearable Data Layer同步到配对的手机端应用 - 手机端应用调用系统分享能力,支持用户将文件发送到邮箱、保存到公共存储或者传输到PC
内容的提问来源于stack exchange,提问作者casella
相关产品推荐
相关产品推荐

