question

Amazon Customer avatar image
Amazon Customer asked

Establishing a downchannel with Okhttp?

Hello, I'm attempting to use Okhttp to communicate with AVS. I'm establishing a downchannel with AVS using a GET call to the directives endpoint. I get a Response object, and the code() method returns 200, but response.body().contentLength() is -1, and trying to read the response body times out (I have the read timeout set to 1 minute). All of my subsequent requests (including the SynchronizeState event that I send right after the GET) return a 400 response code, but response.body().contentLength() is -1 for those too, so I'm having trouble debugging. Any idea what I'm doing wrong? Thanks, Mike
alexa voice service
2 comments
10 |5000

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Hi Amazon Customer,

I am trying to do the same (okhttp3 instead of jetty), but the downchannel never comes back with a response from:

Response response = currentCall.execute(); (The POST part works fine)

I have tried having one new OkHttpClient(); or two, but both approaches fail to respond on the downchannel.

Did you made one or two OkHttpClient()?

Did you experience the same problem.

I would really appreciate some pointers.

Thanks!

0 Likes 0 ·
psoft avatar image psoft Antonio Rodriguez ·

Have you had any luck with OkHttp3 and the downchannel? I am having the same issue as you (see below). I have tried all sorts of combinations to get a response on the downchannel, but no luck so far. I am able to get responses from GET and POSTs, however. According to the Alexa Voice Services' docks, there must be ONE connection to the server. I'm wondering if that is the case with OkHttp3, and how to figure that out and verify that is the case.

0 Likes 0 ·
Eric@Amazon avatar image
Eric@Amazon answered
10 |5000

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Amazon Customer avatar image
Amazon Customer answered
Hi Eric, Thanks for the reply! I was just experimenting with that, but unfortunately I still am not able to read the responses. I have this code: try { Response response = httpClient.newCall(request).execute(); headers = response.headers(); logger.d("startDownchannel: " + response.code() + ", " + response.protocol().name() + ", length:" + response.body().contentLength()); for (int i = 0; i < headers.size(); i++) { logger.d(" " + headers.name(i) + ": " + headers.value(i)); } Buffer buffer = new Buffer(); while (!response.body().source().exhausted()) { long count = response.body().source().read(buffer, 8192); logger.d(""+ buffer.toString()); } listener.onConnected(response.isSuccessful()); } catch (IOException e) { e.printStackTrace(); downchannelThread.interrupt(); } It seems to time out in the exhausted() call, specifically in the waitForIo() call (which calls wait() ) inside okhttp... I tried upping the read timeout to 5 minutes, no dice yet. If it's useful, from those logs, I see: startDownchannel: 200, HTTP_2, length:-1 access-control-allow-origin: * x-amzn-requestid: 0e79fafffe04f803-00003159-00016c01-24511cc6e99ba4d7-5067da5b-3- content-type: multipart/related; boundary=------abcde123; type=application/json OkHttp-Sent-Millis: 1461292505083 OkHttp-Received-Millis: 1461292505421
10 |5000

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Amazon Customer avatar image
Amazon Customer answered
Sorry to double-comment (can't edit I guess), but I wanted to include the stack trace of where it times out: waitForIo():588, FramedStream (okhttp3.internal.framed) access$900():34, FramedStream (okhttp3.internal.framed) waitUntilReadable():376, FramedStream$FramedDataSource (okhttp3.internal.framed) read():342, FramedStream$FramedDataSource (okhttp3.internal.framed) read():35, ForwardingSource (okio) exhausted():60, RealBufferedSource (okio) run():80, AvsClient$1 (com.navdy.client.app.framework.avs)
10 |5000

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Amazon Customer avatar image
Amazon Customer answered
Sweet, I was able to get responses from the events API. So I guess I'm just not understanding how to handle the downchannel in Okhttp. Any tips? Should I be trying to read the response there all the time? I was having issues with the sample app throwing timeout errors so I'm not sure if I should follow the example there. Thanks in advance for any help!
10 |5000

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Eric@Amazon avatar image
Eric@Amazon answered
I'm afraid I don't have much in the way of advice for using OkHTTP specifically. The way we have down channel implemented, we have a separate thread for down channel events. We then block on read, waiting for directives to come in. When they do, we post those directives to a queue accessible outside the thread. If the down channel request ever times out, we immediately re-establish the connection. A couple pieces of advice that may be relevant: Look at your connection timeouts. For the down channel, you probably don't want to have a timeout value. http://stackoverflow.com/questions/25953819/how-to-set-connection-timeout-with-okhttp Per the documentation here ( https://developer.amazon.com/public/solutions/alexa/alexa-voice-service/docs/managing-an-http-2-connection#Maintaining%20an%20HTTP/2%20Connection) you need to send pings to AVS every 5 minutes in order to keep the connection alive. That may be your problem.
10 |5000

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Amazon Customer avatar image
Amazon Customer answered
Thanks so much for your help, sir. I ended up doing just that (no timeout) and I am getting some directives in the downchannel now :) Happy friday :)
1 comment
10 |5000

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Hi Amazon Customer, would you like to share some code of how implement the down channel using Okhttp?

0 Likes 0 ·
psoft avatar image
psoft answered

I am having the same problem with OkHttp/2 and the downchannel being silent. I have tried each of the suggestions above and am still not receiving anything on the downchannel. I get a HTTP code of 200 when connecting to it. I'm also successful in sending SpeechRecognizer event and receiving a SpeechSynthesizer event and playing back the received audio.

I've tried asking AVS to set a timer, which the audio says it will, but I never get the downchannel commands to set one up. Here's a code snippet:

            OkHttpClient downChannelClient = httpClient.newBuilder()
                .connectTimeout(0, TimeUnit.MILLISECONDS)  // 0 => no timeout.
                .readTimeout(0, TimeUnit.MILLISECONDS)
//                .connectionPool(connectionPool)
                .build();

            final Request request = new Request.Builder()
                .url(url)
                .get()
//                .addHeader("Connection", "close")
                .addHeader("Authorization", "Bearer " + this.accessToken)
                .build();
            Log.d(TAG, "downchannel URL ==> " + request.url().toString());
            Log.d(TAG, "downchannel headers ==> " + request.headers().toString());

            Response response = null;
            try
            {
                currentCall = downChannelClient.newCall(request);
                response = currentCall.execute();
                BufferedSource bufferedSource = response.body().source();

                Log.i(TAG, "Downchannel ==> HTTP response code: " + response.code());

                Buffer buffer = new Buffer();

                while (!bufferedSource.exhausted())
                {
                    Log.w(TAG, "downchannel received data!!!");
                    bufferedSource.read(buffer, 8192);
                    Log.d(TAG, "Size of data read: " + buffer.size());
                }

                Log.d(TAG, "Response: " + buffer.toString());
            }
            catch (IOException e)
            {
                Log.d(TAG, "Response with Error", e);
            }
1 comment
10 |5000

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

So,now you solve the problem?

0 Likes 0 ·