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

如何使用SharedPreferences存储BLE扫描任务的时间信息

问题原因

你遇到的崩溃是类型转换错误导致的:SharedPreferences 不支持直接存储Date类型对象,你代码中强行将Date类型转换为Set<String>写入SharedPreferences,运行时会直接抛出ClassCastException异常。
同时你还存在一个逻辑问题:两个BLE设备的RSSI、扫描时间都用同一个key存储,后扫描到的设备数据会直接覆盖之前的数据,根本无法同时保存两个设备的信息。

解决方案

你只需要扫描时间不需要日期,推荐两种实现方案:

方案1:存储毫秒时间戳(推荐,适合需要计算时间差的场景)

SharedPreferences原生支持存储long类型,直接存储时间的毫秒值即可,读写都很方便,计算两个扫描的时间差也不需要额外转换:

存储代码修改(扫描回调部分)

// 设备SimpleBLEBroadcaster1存储逻辑
RSSI1 = result.getRssi();
CurrentTime1 = Calendar.getInstance().getTime();
startTime = System.nanoTime(); // 不要加前面的long,否则是局部变量,全局变量不会被赋值
SharedPreferences.Editor editor= sharedPreferences.edit();
editor.putInt("device1_rssi", RSSI1);
// 存储时间戳,key和设备2区分开
editor.putLong("device1_scan_time", CurrentTime1.getTime());

// 设备SimpleBLEBroadcaster2存储逻辑
RSSI2 = result.getRssi();
CurrentTime2 = Calendar.getInstance().getTime();
stopTime = System.nanoTime();
editor.putInt("device2_rssi", RSSI2);
editor.putLong("device2_scan_time", CurrentTime2.getTime());

editor.apply(); // 用apply比commit效率更高,不需要同步等待写入结果

读取代码修改(GetData方法部分)

public void GetData(){
    peripheralTextView.setText(" ");
    // 读取设备1数据
    int rssi1 = sharedPreferences.getInt("device1_rssi", 0);
    long time1Stamp = sharedPreferences.getLong("device1_scan_time", 0);
    Date time1 = new Date(time1Stamp);
    // 读取设备2数据
    int rssi2 = sharedPreferences.getInt("device2_rssi", 0);
    long time2Stamp = sharedPreferences.getLong("device2_scan_time", 0);
    Date time2 = new Date(time2Stamp);
    // 直接计算时间差,单位是毫秒
    long timeDiff = time2Stamp - time1Stamp;
    // 也可以格式化时间只显示时分秒
    SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss", Locale.getDefault());
    String showTime1 = sdf.format(time1);
    String showTime2 = sdf.format(time2);

    peripheralTextView.append("\n" +"Broadcaster 1: " +"\n" + " 信号强度是 " + rssi1 + " 测量时间:" + showTime1 + "\n" + "Broadcaster 2: " + "\n" + " 信号强度是 " + rssi2 + " 测量时间:" + showTime2  + " 扫描间隔:" + timeDiff + "ms\n");
}

方案2:存储格式化时间字符串(适合仅需要展示不需要计算的场景)

如果你不需要计算时间差,只需要展示扫描时间,可以直接把时间格式化为时分秒的字符串存储,读取后可以直接展示:

// 存储时格式化
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss", Locale.getDefault());
String timeStr1 = sdf.format(CurrentTime1);
editor.putString("device1_scan_time_str", timeStr1);

// 读取时直接拿字符串展示即可
String showTime1 = sharedPreferences.getString("device1_scan_time_str", "未扫描");

额外注意点

你代码中声明的全局startTime和stopTime变量,在扫描回调里又加了long关键字重新声明为局部变量,导致全局变量永远不会被赋值,GetData方法中计算的TimeElapsed永远是0,需要去掉局部变量的long声明,直接给全局变量赋值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 22:06:01