简体   繁体   English

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

[英]Android Bluetooth periodic calls to inputStream and outputStream: inconsistent timestamps

Two bluetooth enabled devices are connected. 连接了两个蓝牙设备。 One sends a periodic timestamp (writeTime) through outputStream to the other, which retrieves the writeTimes via inputStream and attaches its own timestamps (readTime) for comparison. 一个通过outputStream发送一个周期性时间戳(writeTime)到另一个,后者通过inputStream检索writeTimes并附加自己的时间戳(readTime)进行比较。 My goal is to make the readTime equal to the writeTime for each loop. 我的目标是使每个循环的readTime等于writeTime。 The code below causes the writeTimes to increment with a predetermined delay (3 seconds), but the readTimes do not increment. 下面的代码使writeTimes以预定的延迟(3秒)递增,但readTimes不会递增。 The readTimes are fixed at the moment when the two devices connect to one another. 当两个设备相互连接时,读取时间是固定的。 Here are snippets of the outputStream.write and inputStream.read along with sample results. 以下是outputStream.write和inputStream.read的片段以及示例结果。

For the sending device: Loop within a timer having three-second delays between writes to the outputStream: There is a CountDownTimer driving the onTick 对于发送设备:在计时器内循环,在两次写入outputStream之间有三秒的延迟:有一个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) {}

For the receiving device: A read loop (iloop) that iterates the same number of times as the write loop from the sender: 对于接收设备:一个读取循环(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 ;
        }
    }

Screenshot of readarray after it is written: (a loop of five rows with 3 second delay between writes): readarray写入后的屏幕截图:(五行循环,两次写入之间有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

Conclusion: The inputStream is being read with a timestamp equal to the beginning of the socket connection. 结论:正在使用与套接字连接的开始相等的时间戳读取inputStream。 (In the example output, I waited ten seconds after connecting before intitiating the write to the outputStream). (在示例输出中,我在连接后等待了十秒钟,然后才开始写入outputStream)。 How do I get readTime to reflect the writeTime? 如何获取readTime以反映writeTime? My ultimate goal is to read from an inputStream at a periodic rate rather than batch processing a large number of small reads within a single batch. 我的最终目标是以周期性的速率从inputStream读取数据,而不是批量处理单个批处理中的大量小读取。 I want to access each read in real time and know when the read took place. 我想实时访问每个读取,并知道读取发生的时间。

Update on this post: I took the insight from Ole VV and simply moved the following three lines of code from OUTSIDE the read loop (iloop) to INSIDE the iloop just above readTime 这篇文章的更新:我从Ole VV获得了见识,并将以下三行代码从读取循环(iloop)外部移到了readTime上方的INSIDE内部

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

This solved the problem. 这样就解决了问题。 I should have understood that calendar is an instance of Calendar whose characteristic, calendar.getTime(), does not change with the ticking of the clock. 我应该知道,日历是Calendar的一个实例,其特性calendar.getTime()不会随着时钟的滴答而改变。 The outdated SimpeDateFormat was not at fault although Ole VVs suggestion to replace it might be useful in other applications. 尽管Ole VV建议更换它,但过时的SimpeDateFormat并没有错,在其他应用程序中可能很有用。

java.time java.time

To put the current time, eg, the time of a read from your stream, into a string: 将当前时间(例如,从流中读取的时间)放入字符串中:

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

The DateTimeFormatter may be created outside your loop, but you must call LocalTime.now inside the loop to get the time of the current iteration. 可以在循环外部创建DateTimeFormatter ,但是必须在循环内部调用LocalTime.now才能获取当前迭代的时间。

Example result in my locale is a string of 11.57.13 . 在我的语言环境中,示例结果是字符串11.57.13 Please substitute your desired time zone where I put America/Dawson. 请替换您要放置美国/道森的所需时区。

I am using java.time, the modern java date and time API, because the date and time classes that you were using, Calendar and SimpleDateFormat , always had design problems and now are long outdated. 我使用的是现代Java日期和时间API java.time,因为您使用的日期和时间类CalendarSimpleDateFormat始终存在设计问题,并且现在已经过时了。 Consider not using them anymore. 考虑不再使用它们。

What went wrong in your code? 您的代码出了什么问题?

You haven't provided a complete example, so the snippets from the question cannot be compiled and run as they stand, and I have not been able to veryfy. 您尚未提供完整的示例,因此问题中的代码片段无法按现状进行编译和运行,而我也无法做到。 It seems , however, that you have created a Calendar object outside the loop and that you don't modify the time of that Calendar object later. 但是, 似乎您已经在循环外创建了Calendar对象,并且以后没有修改该Calendar对象的时间。 Therefore it keeps its time, and that time is the time you get every time through your loop. 因此,它保持其时间,而时间就是您每次循环所获得的时间。 (By contrast, on your writing side you are creating a new Calendar object in every invocation of onTick , which is why you get the current time each time.) (相比之下,在书写方面,每次onTick调用都在创建一个新的Calendar对象,这就是每次获取当前时间的原因。)

Question: Can I use java.time on Android? 问题:我可以在Android上使用java.time吗?

Yes, java.time works nicely on older and newer Android devices. 是的, java.time在较新和较旧的Android设备上java.time正常运行。 It just requires at least Java 6 . 它至少需要Java 6

  • In Java 8 and later and on new Android devices (from API level 26) the new API comes built-in. 在Java 8和更高版本以及新的Android设备(API级别26)中,内置了新API。
  • In Java 6 and 7 get the ThreeTen Backport, the backport of the new classes (ThreeTen for JSR 310, where the modern API was first described). 在Java 6和7中,获取ThreeTen Backport,即新类的backport(用于JSR 310的ThreeTen,首次描述了现代API)。
  • On (older) Android, use the Android edition of ThreeTen Backport. 在(较旧的)Android上,使用Android版本的ThreeTen Backport。 It's called ThreeTenABP. 它称为ThreeTenABP。 Make sure you import the date and time classes from package org.threeten.bp and subpackages. 确保从包org.threeten.bp和子包中导入日期和时间类。

Links 链接

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM