1

I am sending an IR signal to the IR receiver which is passed through the BT module to the InputStream of the Android application. Every time I press a button on the emitter, I send 100 bytes which then I expect to get into the InputStream (is there a way to handle an exception when there is no 100 bytes because the packet got corrupted?).

This is my code for reading InputStream and putting values into the byte[] buffer:

 public int read(final InputStream input, final byte[] buffer) throws IOException {
        int remaining = buffer.length;
        try {
            Thread.sleep(100); // Not sure if this helps anything, just a desperate move
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        while (remaining > 0) {
            final int location = buffer.length - remaining;
            final int count = input.read(buffer, location, remaining);
            if (count == -1) { // EOF
                break;
            }
            remaining -= count;
        }
        return buffer.length - remaining;
    }

It works fine for couple of times, but at some point, usually after 4th try, I am getting those mentioned bytes without the first byte. It seems like package has been corrupted at some point and only 99 bytes were sent and then subsequently the next sending of the bytes, result in putting one byte to the previous buffer and losing the first byte.

However interesting is, that packets have always 100 bytes, and they are not dummy (zero values) in there.

Those values are accelerometer coordinates (doesn't really matter).

Example correct values:

0 = 1
1 = 35
2 = 0
3 = -27
4 = 19
5 = -4
6 = 64
7 = 10
8 = -7
9 = 66
10 = 10
11 = 0
12 = 66
13 = 4
14 = -1
15 = 64
16 = 8
17 = -1
18 = 67
19 = 7
20 = -3
21 = 66
22 = 6
23 = -1
24 = 65
25 = 7
26 = -2
27 = 66
28 = 7
29 = -3
30 = 65
31 = 6
32 = -3
33 = 67
34 = 6
35 = -2
36 = 66
37 = 7
38 = -2
39 = 66
40 = 4
41 = -3
42 = 66
43 = 6
44 = -3
45 = 66
46 = 6
47 = -3
48 = 66
49 = 5
50 = -3
51 = 66
52 = 6
53 = -2
54 = 65
55 = 5
56 = -3
57 = 65
58 = 6
59 = -3
60 = 66
61 = 6
62 = -3
63 = 66
64 = 6
65 = -3
66 = 66
67 = 6
68 = -2
69 = 66
70 = 5
71 = -3
72 = 66
73 = 5
74 = -3
75 = 66
76 = 5
77 = -2
78 = 66
79 = 5
80 = -3
81 = 66
82 = 5
83 = -3
84 = 66
85 = 6
86 = -2
87 = 66
88 = 5
89 = -2
90 = 65
91 = 5
92 = -2
93 = 65
94 = 5
95 = -2
96 = 66
97 = 4
98 = -2
99 = 66

Example incorrect values (it can also happen that first byte is missing, however in this case there is one more byte at the beginning):

0 = 66
1 = 1
2 = 35
3 = 3
4 = 10
5 = -14
6 = -17
7 = 81
8 = 15
9 = -5
10 = 64
11 = 14
12 = -4
13 = 68
14 = 7
15 = -5
16 = 69
17 = 9
18 = -5
19 = 78
20 = 15
21 = -3
22 = 77
23 = 16
24 = -2
25 = 72
26 = 20
27 = 3
28 = 64
29 = 20
30 = 8
31 = 55
32 = 22
33 = 16
34 = 50
35 = 22
36 = 19
37 = 52
38 = 11
39 = 13
40 = 50
41 = 6
42 = 14
43 = 50
44 = 9
45 = 13
46 = 54
47 = 12
48 = 9
49 = 63
50 = 16
51 = 12
52 = 67
53 = 6
54 = 0
55 = 74
56 = 8
57 = -4
58 = 75
59 = 13
60 = -2
61 = 68
62 = 17
63 = -5
64 = 79
65 = 8
66 = -8
67 = 62
68 = 15
69 = -8
70 = 65
71 = 13
72 = -7
73 = 67
74 = 8
75 = -6
76 = 66
77 = 9
78 = -3
79 = 67
80 = 8
81 = -4
82 = 66
83 = 7
84 = -4
85 = 65
86 = 8
87 = -4
88 = 67
89 = 7
90 = -4
91 = 66
92 = 7
93 = -3
94 = 67
95 = 6
96 = -4
97 = 66
98 = 6
99 = -3

Any idea how to solve it? Note, I don't send 2 packages of bytes twice in less than 3 seconds, if that helps in finding a solution.

durron597
  • 31,968
  • 17
  • 99
  • 158
Ondrej Tokar
  • 4,898
  • 8
  • 53
  • 103

1 Answers1

1

InputStream is a very low level API, you almost never want to use it directly. In this case, the wrapper that is most suited to your purposes is DataInputStream, which has a readFully method that seems to be what you want; the code is much simpler and shorter.

public void read(final InputStream input, final byte[] buffer) throws IOException, EOFException {
  DataInputStream dataStream = new DataInputStream(input);
  dataStream.readFully(buffer, 0, buffer.length);
}

If this doesn't work, then I suspect the problem is something with the data stream from the IR itself.


If you need to read from the stream with a timeout (in the case of a corrupted packet), then this method is not advised, because it will block, as you've already noticed. In such a case, I recommend reading the information in this question: Is it possible to read from a InputStream with a timeout?

Community
  • 1
  • 1
durron597
  • 31,968
  • 17
  • 99
  • 158
  • 1
    I can't believe that. You were able to solve my long term issue... I love that feeling. Thanks a lot! I wouldn't even believe that somebody could understand my issue not even solve it. :) – Ondrej Tokar Aug 29 '15 at 19:41
  • I have one issue though. My app is hanging there if the package is corrupted (has less than 100 elements). Then it waits for my other press of the button and it fills up the missing bytes. What I want is to destroy the old package if it was corrupted and get only new one. Any idea? Thanks! :) – Ondrej Tokar Aug 29 '15 at 20:13
  • 1
    @OndrejTokar `DataInputStream` is not a good choice if you need the reading to timeout. See my edit for an alternative. – durron597 Aug 29 '15 at 20:17
  • Thank you. I can see the timeout solution uses another thread. Is that necessary? May I just use Thread.sleep on the current thread? Which will actually block the rest of the code? – Ondrej Tokar Aug 29 '15 at 20:27