Android 蓝牙定期调用 inputStream 和 outputStream:时间戳不一致

Android Bluetooth periodic calls to inputStream and outputStream: inconsistent timestamps

连接了两个蓝牙设备。一个通过 outputStream 向另一个发送周期性时间戳 (writeTime),另一个通过 inputStream 检索 writeTimes 并附上自己的时间戳 (readTime) 以进行比较。我的目标是使每个循环的 readTime 等于 writeTime。下面的代码使 writeTimes 以预定延迟(3 秒)递增,但 readTimes 不递增。当两个设备相互连接时,readTimes 是固定的。以下是 outputStream.write 和 inputStream.read 的片段以及示例结果。

对于发送设备:在写入输出流之间有三秒延迟的计时器内循环:有一个 CountDownTimer 驱动 onTick

    public void onTick(long millisUntilFinished) {
        Calendar calendar = Calendar.getInstance();
        SimpleDateFormat mdformat = new SimpleDateFormat("HH:mm:ss");
        String thisTime = mdformat.format(calendar.getTime());
        tV.setText("Current Time: " + thisTime);  // thisTime  increments on the display in real time.
        try {
            thisTime=thisTime+ "^";  // "^" added as the end of a line
            outputStream.write(thisTime.getBytes(Charset.forName("UTF-8")));
        } catch (IOException e) {}

对于接收设备:一个读取循环 (iloop),其迭代次数与发送方的写入循环相同:

        for (iloop =1;iloop<6;iloop++) {
            inputStream = socket.getInputStream();
            byte[] inbyte = new byte[1];
            int inbuffer;
            BufferedReader br = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
            writeTime = "";
            eol = false;   
            do {
                inbuffer = br.read();
                if (inbuffer != 94) { // character "^" (byte 94) triggers an end-of-line for each read.

                    ByteArrayOutputStream bos = new ByteArrayOutputStream();
                    DataOutputStream dos = new DataOutputStream(bos);
                    dos.writeInt(inbuffer);
                    inbyte = bos.toByteArray();
                    next = new String(inbyte, "UTF-8");
                    writeTime = writeTime + next;
                } else {eol = true;}

            } while (!eol);
            readTime = mdformat.format(calendar.getTime());
            readarray[iloop] = "\r\n" + writeTime + "  " + readTime ;
        }
    }

readarray 写入后的屏幕截图:(5 行的循环,写入之间延迟 3 秒):

14:44:12  14:44:02
14:44:15  14:44:02
14:44:18  14:44:02
14:44:21  14:44:02
14:44:24  14:44:02

结论:正在读取输入流,其时间戳等于套接字连接的开始时间。 (在示例输出中,我在连接后等待十秒钟,然后才开始写入 outputStream)。如何获取 readTime 以反映 writeTime?我的最终目标是以周期性速率从 inputStream 中读取,而不是在单个批次中批处理大量小读取。我想实时访问每个读取并知道读取发生的时间。

更新post: 我从 Ole VV 那里得到了启发,并简单地将以下三行代码从读取循环 (iloop) 外部移至 iloop 内部,就在 readTime

上方
  Calendar calendar = Calendar.getInstance();
  SimpleDateFormat mdformat = new SimpleDateFormat("HH:mm:ss");
  String strDate;

这解决了问题。我应该明白,calendar 是 Calendar 的一个实例,它的特性 calendar.getTime() 不会随着时钟的滴答声而改变。 过时的 SimpeDateFormat 并没有错,尽管 Ole VV 的替换建议可能对其他应用程序有用。

java.time

将当前时间(例如,从流中读取的时间)放入字符串中:

    DateTimeFormatter timeFormatter
            = DateTimeFormatter.ofLocalizedTime(FormatStyle.MEDIUM);
    String readTime = LocalTime.now(ZoneId.of("America/Dawson"))
            .format(timeFormatter);

DateTimeFormatter可以在你的循环外创建,但你必须在循环内调用LocalTime.now来获取当前迭代的时间。

我的语言环境中的示例结果是 11.57.13 的字符串。请在我输入 America/Dawson.

的地方替换你想要的时区

我正在使用 java.time,现代 java 日期和时间 API,因为您使用的日期和时间 类,CalendarSimpleDateFormat,总是有设计问题,现在早就过时了。考虑不再使用它们。

你的代码出了什么问题?

你没有提供完整的例子,所以问题中的片段无法编译,运行按原样,我无法验证。但是,似乎,您在循环外创建了一个 Calendar 对象,并且您稍后没有修改该 Calendar 对象的时间。因此它保持它的时间,那个时间就是你每次通过循环得到的时间。 (相比之下,在你的写作方面,你在每次调用 onTick 时创建一个新的 Calendar 对象,这就是你每次都获得当前时间的原因。)

问题:我可以在 Android 上使用 java.time 吗?

是的,java.time 在新旧 Android 设备上都能很好地工作。它只需要至少 Java 6.

  • 在 Java 8 及更高版本以及新的 Android 设备(来自 API 级别 26)中,新的 API 是内置的。
  • 在 Java 6 和 7 中获取 ThreeTen Backport,新 类 的 backport(ThreeTen 用于 JSR 310,其中现代 API 首次被描述)。
  • 在(较旧的)Android 上,使用 ThreeTen Backport 的 Android 版本。它叫做 ThreeTenABP。确保从包 org.threeten.bp 和子包中导入日期和时间 类。

链接