0

The code below has a lot of debug print statements. What I've found when googling and browsing other stack overflow posts is that people usually get a json file back after they make the synchronize event request, but I just get nothing for around 30 seconds when calling Log.d("syncResponse_body", "Result: " + response.body().string());, and then a SocketTimeoutException. Here is the amazon documentation I am following: https://developer.amazon.com/en-US/docs/alexa/alexa-voice-service/manage-http2-connection.html

private Response makeSyncRequest(OkHttpClient downChannelClient, String accessToken) throws IOException {
    final Request getRequest = new Request.Builder()
        .url("https://alexa.na.gateway.devices.a2z.com/" + AVS_API_VERSION + "/directives")//endpoint url
        .get()
        .addHeader("authorization", "Bearer " + accessToken)
        .build();

    Log.d("Request_header", getRequest.toString());
    Call currentCall = downChannelClient.newCall(getRequest);
    Response syncResponse = currentCall.execute();
    Log.d("Response_success", String.valueOf(syncResponse.isSuccessful()));
    Log.d("Response_str", syncResponse.toString());

    return syncResponse;
}

private Response syncronizeWithAVS(OkHttpClient downChannelClient, String accessToken) throws IOException {
    Response syncResponse = makeSyncRequest(downChannelClient, accessToken);

    String msgId = UUID.randomUUID().toString();
    String speakToken = "";
    long offsetMili = 20; // if lags put down to 10.
    String playerActivity = "PLAYING";

    // ------------------------------
    final String JSON_SYNC = "{\"context\":[{\"header\":{\"namespace\":\"SpeechRecognizer\",\"name\":\"RecognizerState\"},\"payload\":{\"wakeword\":\"ALEXA\"}},{\"header\":{\"namespace\":\"SpeechSynthesizer\",\"name\":\"SpeechState\"},\"payload\":{\"token\":\"" + speakToken + "\",\"offsetInMilliseconds\":" + offsetMili + ",\"playerActivity\":\"" + playerActivity + "\"}}],\"event\":{\"header\":{\"namespace\":\"System\",\"name\":\"SynchronizeState\",\"messageId\":\"" + msgId + "\"},\"payload\":{}}}";

    List<MultipartBody.Part> partList = new ArrayList<>();
    MultipartBody.Part syncPart = MultipartBody.Part.create(Headers.of("Content-Disposition", "form-data; name=\"metadata\""), RequestBody.create(JSON_SYNC, JSON_TYPE));
    partList.add(syncPart);

    RequestBody body = new MultipartBody(ByteString.encodeUtf8(BOUNDARY_TERM), MultipartBody.FORM, partList);

    Log.d("part", syncPart.headers().toString());
    Log.d("body", body.contentType().toString());

    final Request postRequest = new Request.Builder()
            .url("https://alexa.na.gateway.devices.a2z.com/" + AVS_API_VERSION + "/events")//endpoint url
            .post(body)
            .addHeader("authorization", "Bearer " + accessToken)
            .build();

    Log.d("post_request", postRequest.toString());
    Log.d("post_req_body", JSON_SYNC);

    Response postResponse = null;
    try {
        postResponse = downChannelClient.newCall(postRequest).execute();
        Log.d("Post_succes", "" + postResponse.isSuccessful());
        Log.d("Post_succes", "" + postResponse.toString());
        Log.d("Post_Response", "Result: " + postResponse.body().string());

    } catch (IOException e) {
        e.printStackTrace();
    }

    return syncResponse;
}

private void login(AuthorizeResult authorizeResult) {
    ...
    Response response = syncronizeWithAVS(downChannelClient, accessToken);
    Log.d("syncResponse_body", "Result: " + response.body().string());
    ...
}

After logging into amazon to get the access token, this is the output I get:

D/accessToken: authorizeResult.toString(): com.amazon.identity.auth.device.api.authorization.AuthorizeResult@f028508b
    accessToken: <censored accesstoken for this forum post>
D/Request_header: Request{method=GET, url=https://alexa.na.gateway.devices.a2z.com/v20160207/directives, headers=[authorization:Bearer <censored accesstoken for this forum post>]}
D/Response_success: true
D/Response_str: Response{protocol=h2, code=200, message=, url=https://alexa.na.gateway.devices.a2z.com/v20160207/directives}
D/part: Content-Disposition: form-data; name="metadata"
D/body: multipart/form-data; boundary=------------------------qM9tn4VZyj
D/post_request: Request{method=POST, url=https://alexa.na.gateway.devices.a2z.com/v20160207/events, headers=[authorization:Bearer <censored accesstoken for this forum post>]}
D/post_req_body: {"context":[{"header":{"namespace":"SpeechRecognizer","name":"RecognizerState"},"payload":{"wakeword":"ALEXA"}},{"header":{"namespace":"SpeechSynthesizer","name":"SpeechState"},"payload":{"token":"","offsetInMilliseconds":20,"playerActivity":"PLAYING"}}],"event":{"header":{"namespace":"System","name":"SynchronizeState","messageId":"c5488d48-c758-46a0-aeea-e305a452df90"},"payload":{}}}
D/Post_succes: true
    Response{protocol=h2, code=204, message=, url=https://alexa.na.gateway.devices.a2z.com/v20160207/events}
D/Post_Response: Result: 

And then, after 30 seconds,

W/System.err: java.net.SocketTimeoutException: timeout
        at okhttp3.internal.http2.Http2Stream$StreamTimeout.newTimeoutException(Http2Stream.kt:677)
        at okhttp3.internal.http2.Http2Stream$StreamTimeout.exitAndThrowIfTimedOut(Http2Stream.kt:686)
        at okhttp3.internal.http2.Http2Stream$FramingSource.read(Http2Stream.kt:382)
W/System.err:     at okhttp3.internal.connection.Exchange$ResponseBodySource.read(Exchange.kt:276)
        at okio.Buffer.writeAll(Buffer.kt:1655)
        at okio.RealBufferedSource.readString(RealBufferedSource.kt:95)
        at okhttp3.ResponseBody.string(ResponseBody.kt:187)
        at aut.rnd.alexa.ui.account.AccountFragment.login(AccountFragment.java:362)
        at aut.rnd.alexa.ui.account.AccountFragment.access$300(AccountFragment.java:65)
        at aut.rnd.alexa.ui.account.AccountFragment$TokenListener.onSuccess(AccountFragment.java:381)
        at aut.rnd.alexa.ui.account.AccountFragment$TokenListener.onSuccess(AccountFragment.java:373)
        at com.amazon.identity.auth.device.api.authorization.AuthorizationManager$3.onSuccess(AuthorizationManager.java:276)
        at com.amazon.identity.auth.device.thread.AuthzCallbackFuture$1.onSuccess(AuthzCallbackFuture.java:36)
        at com.amazon.identity.auth.device.thread.MAPCallbackFuture.onSuccess(MAPCallbackFuture.java:88)
        at com.amazon.identity.auth.device.authorization.InternalAuthManager$2$1.onSuccess(InternalAuthManager.java:119)
        at com.amazon.identity.auth.device.authorization.TokenHelper.getToken(TokenHelper.java:65)
W/System.err:     at com.amazon.identity.auth.device.authorization.InternalAuthManager$2.run(InternalAuthManager.java:115)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:923)
gogobebe2
  • 324
  • 2
  • 4
  • 18

1 Answers1

1

The guide you mention has this info:

Read timeouts: Because AVS requires a downchannel stream to be open between AVS and a client for the life of the connection, set any read timeout for your client to at least 60 minutes.

So you should certainly increase the read timeout of this connection. To do that, use this code (found in this answer):

downChannelClient.setReadTimeout(60, TimeUnit.MINUTES);
francis duvivier
  • 2,056
  • 11
  • 17