2017-02-13 28 views
3

Я использую OkHttp v3.6.0 на Android для общения с AVS v20160207. Мне удастся связаться с AVS в канале Events для отправки события SpeechRecognizer и получения соответствующей директивы SpeechSynthesizer.OkHttp полузакрытый поток для downvannel AVS на Android

При установлении соединения с нисходящим каналом я получаю успешный ответ HTTP 200 Success, а затем блокирую поток для получения входящих данных. Когда я прошу Алекса установить «таймер на 5 секунд», я получаю ее подсказку, говоря, что она запустит таймер, но я никогда не получаю никаких указаний на нисходящем канале, чтобы сказать мне, чтобы установить таймер вверх.

Что интересно, как уже отмечалось выше, я получаю успех HTTP 200 из ниспадающего канала, а затем блокирую функцию response.body(). Source(). истощен(). Но после 10 минут блокируется и ничего не получает, поток замыкаются, и я получаю следующее исключение:

Ответ с ошибкой okhttp3.internal.http2.StreamResetException: поток сброса: ОТМЕНА на 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) на 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)

Обратите внимание, что я попробовал все предложения, найденных в этой теме: 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 гласит, что клиент должен иметь одно соединение с сервером, поэтому потоки POST и GETs создаются для этого одного соединения, а также один канал в полузакрытом состоянии потока. Поддерживает ли OkHttp2 это?

+0

Hi @Paul У меня такая же проблема, вы найдете решение? – leobelizquierdo

+0

@leobelizquierdo, я все еще ищу его. Я попытался реализовать каждое из предложений, которые мог найти, но ничего не сработало. – Paul

+0

Не могли бы вы рассказать мне, какое событие я должен ожидать, чтобы отправить что-то через нисходящий канал? SynchronizeState является одним из таких? должен ли контекст, который я передаю серверу, в ответе, находится ли он в том же потоке или в нисходящем канале? Я получаю 204 для события SynchronizeState, но я ничего не получаю от нисходящего канала, никакой идеи? – leobelizquierdo

ответ

1

Наконец, я получаю данные с сервера в нисходящем канале. То, что я делаю, было SynchronizeState после того, как я получил ответ 200, когда создаю downchannel. Док говорит:

  1. Чтобы установить downchannel поток ваш клиент должен сделать запрос GET к/{{API версии}}/директивы в течение 10 секунд после открытия соединения с AVS. Запрос должен выглядеть так:

  2. После установки потока в канале, ваш клиент должен синхронизировать состояния компонентов с AVS. Для этого требуется сделать запрос POST в/{{API version}}/events в новом потоке событий в существующем соединении (Примечание. Не открывайте новое соединение). Этот поток событий должен быть закрыт, когда ваш клиент получает ответ (директиву). Ниже приведено пример 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()); 
} 
+0

большое спасибо. Моя проблема оказалась не в одиночном OkHttpClient. Ваше предложение указывало путь! – Paul

+0

Я использовал Singleton OkHttpClient, но после 'SynchronizeState' не получал никаких данных. Можете ли вы предложить какой-либо код для разбора ответа сервера с помощью OkHttpClient на Android? Пожалуйста, примите мой ответ, если он поможет вам, спасибо. – leobelizquierdo

+0

Чтобы проанализировать информацию, отправленную с AVS, я использую Apache FileUpload [link] (http://commons.apache.org/proper/commons-fileupload/) и IOUtils. – Paul