如何使用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
相关产品推荐
相关产品推荐

