Android Bluetooth периодические вызовы inputStream и outputStream: несовместимые временные метки - PullRequest
0 голосов
/ 17 ноября 2018

Подключены два устройства с поддержкой Bluetooth.Один отправляет периодическую метку времени (writeTime) через outputStream другому, который извлекает writeTimes через inputStream и присоединяет свои собственные метки времени (readTime) для сравнения.Моя цель - сделать readTime равным writeTime для каждого цикла.Приведенный ниже код заставляет writeTimes увеличиваться с заданной задержкой (3 секунды), но readTimes не увеличивается.Чтение времени фиксируется в тот момент, когда два устройства соединяются друг с другом.Вот фрагменты outputStream.write и inputStream.read вместе с примерами результатов.

Для отправляющего устройства: Цикл в таймере с задержкой в ​​три секунды между записями в 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) {}

Для принимающего устройства: цикл чтения (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 после того, как онзаписано: (цикл из пяти строк с задержкой в ​​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

Вывод: InputStream читается с отметкой времени, равной началу соединения с сокетом.(В примере вывода я подождал десять секунд после подключения, прежде чем приступить к записи в outputStream).Как я могу получить readTime для отражения writeTime?Моей конечной целью является чтение из inputStream с периодической скоростью, а не пакетная обработка большого количества небольших операций чтения в одном пакете.Я хочу получить доступ к каждому чтению в режиме реального времени и знать, когда это произошло.

Обновление этого поста: я получил представление от Ole VV и просто переместил следующие три строки кода из ВНЕШНЕГО цикла чтения (iloop) ВНУТРИ iloop чуть выше readTime

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

Это решило проблему.Я должен был понять, что календарь является экземпляром Календаря, чья характеристика calendar.getTime () не изменяется с тиканием часов.Устаревший SimpeDateFormat не был виноват, хотя предложение Ole VV заменить его может быть полезно в других приложениях.

1 Ответ

0 голосов
/ 17 ноября 2018

java.time

Чтобы поместить текущее время, например время чтения из вашего потока, в строку:

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

DateTimeFormatter может быть создан вне вашего цикла, но вы должны вызвать LocalTime.now внутри цикла, чтобы получить время текущей итерации.

Примером результата в моей локали является строка 11.57.13. Пожалуйста, укажите желаемый часовой пояс, в который я поместил Америку / Доусона.

Я использую java.time, современный API даты и времени java, потому что используемые вами классы даты и времени, Calendar и SimpleDateFormat, всегда имели проблемы с дизайном и теперь давно устарели. Не используйте их больше.

Что пошло не так в вашем коде?

Вы не предоставили полный пример, поэтому фрагменты из вопроса не могут быть скомпилированы и запущены в том виде, в котором они стоят, и я не смог их найти. кажется , однако, что вы создали Calendar объект вне цикла и что вы не изменили время этого Calendar объекта позже. Следовательно, оно сохраняет свое время, и это время - время, которое вы получаете каждый раз в цикле. (Напротив, на вашей стороне записи вы создаете новый Calendar объект при каждом вызове onTick, поэтому вы каждый раз получаете текущее время.)

Вопрос: Могу ли я использовать java.time на Android?

Да, java.time прекрасно работает на старых и новых устройствах Android. Для этого требуется как минимум Java 6 .

  • В Java 8 и более поздних версиях и на новых устройствах Android (с уровня API 26) новый API поставляется встроенным.
  • В Java 6 и 7 получают ThreeTen Backport, бэкпорт новых классов (ThreeTen для JSR 310, где впервые был описан современный API).
  • На (более старой) версии Android используйте версию Android ThreeTen Backport. Это называется ThreeTenABP. Убедитесь, что вы импортируете классы даты и времени из пакета org.threeten.bp и подпакетов.

Ссылки

...