3

我在 Android 上使用 OkHttp v3.6.0 与 AVS v20160207 进行通信。我成功地在事件通道上与 AVS 通信,以发送 SpeechRecognizer 事件和接收匹配的 SpeechSynthesizer 指令。

建立与下行通道的连接时,我收到 HTTP 200 Success 的成功响应,然后阻塞流以接收入站数据。当我要求 Alexa 设置“定时器 5 秒”时,我收到她的提示,说她将启动定时器,但我从未在下行通道上收到任何指令告诉我设置定时器。

同样有趣的是,如上所述,我从下行通道收到 HTTP 200 成功,然后可以阻止 response.body().source()。筋疲力尽的()。但是在 10 分钟被阻止并且没有收到任何内容后,流被关闭,我收到以下异常:

响应错误 okhttp3.internal.http2.StreamResetException:流已重置:在 okhttp3.internal.http2.Http2Stream$FramingSource.checkNotClosed(Http2Stream.java:436) 在 okhttp3.internal.http2.Http2Stream$FramingSource.read(Http2Stream. java:338) 在 okio.ForwardingSource.read(ForwardingSource.java:35) 在 okio.RealBufferedSource$1.read(RealBufferedSource.java:409) 在 java.io.InputStream.read(InputStream.java:101) 在 com.example.demo.alexaassistant.AlexaVoiceServices.interfaces.DownChannelRunnable.run(DownChannelRunnable.java:192) 在 java.lang.Thread.run(Thread .java:761)192) 在 java.lang.Thread.run(Thread.java:761)192) 在 java.lang.Thread.run(Thread.java:761)

请注意,我已经尝试了此线程中的所有建议: 使用 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();
    }
}

编辑

亚马逊的文档说,客户端需要与服务器建立一个连接,因此 POST 和 GETs 流被发送到该连接以及处于半关闭流状态的一个下行通道。OkHttp2 支持这个吗?

4

1 回答 1

1

最后,我现在正在下行通道中从服务器接收数据。我所做的是SynchronizeState在创建下行通道时得到200响应之后。医生说:

  1. 要建立下行通道流,您的客户端必须在打开与 AVS 的连接后 10 秒内向 /{{API version}}/directives 发出 GET 请求。请求应如下所示:

  2. 建立下行通道流后,您的客户端必须将其组件的状态与 AVS 同步。这需要在现有连接上的新事件流上向 /{{API version}}/events 发出 POST 请求(注意:不要打开新连接)。当您的客户端收到响应(指令)时,应关闭此事件流。以下是一个 SynchronizeState 事件示例:

希望这有帮助。我现在正在努力尝试解析下行通道中的结果。您的代码应该:

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

...

synchronizeState();

....

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());
}
于 2017-02-22T21:36:38.917 回答