I am using OkHttp v3.6.0 on Android for communicating with AVS v20160207. I am successful in communicating with AVS on the Events channel for both sending SpeechRecognizer Event and receiving the matching SpeechSynthesizer directive.
When establishing a connection to downchannel, I receive a successful response of HTTP 200 Success and then block on the stream to receive inbound data. When I ask Alexa to set a "timer for 5 seconds", I receive her prompt saying she will start the timer but I never receive any directives on the downchannel to tell me to set the timer up.
What's also interesting, as noted above, I receive a HTTP 200 success from the downchannel and then can block on the response.body().source(). exhausted(). But after 10 minutes of being blocked and not receiving anything, the stream is CLOSED and I receive the following exception:
Response with Error okhttp3.internal.http2.StreamResetException: stream was reset: CANCEL at okhttp3.internal.http2.Http2Stream$FramingSource.checkNotClosed(Http2Stream.java:436) at okhttp3.internal.http2.Http2Stream$FramingSource.read(Http2Stream.java:338) at okio.ForwardingSource.read(ForwardingSource.java:35) at okio.RealBufferedSource$1.read(RealBufferedSource.java:409) at java.io.InputStream.read(InputStream.java:101) at com.example.demo.alexaassistant.AlexaVoiceServices.interfaces.DownChannelRunnable.run(DownChannelRunnable.java:192) at java.lang.Thread.run(Thread.java:761)
Note that I have tried all of the suggestions found in this thread: Establishing a downchannel with Okhttp?
private static final long CONNECTION_POOL_TIMEOUT_MILLISECONDS = 60 * 60 * 1000;
ConnectionPool connectionPool = new ConnectionPool(5,
CONNECTION_POOL_TIMEOUT_MILLISECONDS, TimeUnit.MILLISECONDS);
/**
* Create a customized HTTP/2 interface.
*
* For the AVS's downchannel, we need to
* disable the timeout on the read.
*/
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("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);
}
finally
{
if (response != null)
{
response.close();
}
}
EDIT:
Amazon's documentation says that the client needs to have ONE connection to the server so POSTs and GETs streams are made to that one connection as well as the one downchannel in a half-closed stream state. Does OkHttp2 support this?