public InteractionClient(
      Context context,
      AWSCredentialsProvider credentialsProvider,
      Regions region,
      InteractionConfig interactionConfig,
      ClientConfiguration clientConfiguration) {

    if (context == null) {
      throw new InvalidParameterException("Context cannot be null.");
    } else {
      this.context = context;
    }

    // Check if all necessary credentials are available.
    if (credentialsProvider == null) {
      throw new InvalidParameterException("Credentials are not set.");
    }

    if (interactionConfig == null) {
      throw new InvalidParameterException("Interaction config is not set.");
    }

    if ((interactionConfig.getUserId() == null || interactionConfig.getUserId().isEmpty())
        && !(credentialsProvider instanceof CognitoCredentialsProvider)) {
      throw new InvalidParameterException(
          "User id must be set in the config or Amazon Cognito Identity must used as the credentials provider");
    }

    this.interactionConfig = interactionConfig;
    this.credentialsProvider = credentialsProvider;
    this.interactionListener = new DefaultInteractionListener();

    // Create service low-level client.
    if (null == clientConfiguration) {
      clientConfiguration = new ClientConfiguration();
    }

    String userAgent = INTERACTION_CLIENT_USER_AGENT;

    if (!StringUtils.isBlank(clientConfiguration.getUserAgent())) {
      userAgent += clientConfiguration.getUserAgent();
    }

    clientConfiguration.setUserAgent(userAgent);

    amazonlex = new AmazonLexRuntimeClient(credentialsProvider, clientConfiguration);
    amazonlex.setRegion(Region.getRegion(region));
  }
  /**
   * Invokes the Android {@link MediaPlayer} to playback audio if audio playback was requested, and
   * continues to analyze the response. If the response does not contain audio stream or if audio
   * playback was not requested, continues to analyze the response.
   *
   * @param handler {@link Handler}, to interact with app components in the main thread.
   * @param result {@link PostContentResult}, response from the Amazon Lex service.
   * @param client {@link InteractionClient}, reference to this object.
   * @param responseMode {@link ResponseType}, current response type.
   */
  private void processResponseAudioPlayback(
      final Handler handler,
      final PostContentResult result,
      final InteractionClient client,
      final ResponseType responseMode,
      final ResponseType requestType) {
    // Check if response is audio and audio playback is requested.
    if (ResponseType.AUDIO_MPEG.equals(responseMode) && interactionConfig.isEnableAudioPlayback()) {
      this.lMediaPlayer = new MediaPlayer();
      this.lMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
      try {
        setAudioPlaybackState(BUSY);
        File tempAudioFile = File.createTempFile("lex_temp_response", "mp3", context.getFilesDir());
        tempAudioFile.deleteOnExit();
        // Media player listeners.
        lMediaPlayer.setOnErrorListener(
            new MediaPlayer.OnErrorListener() {
              @Override
              public boolean onError(final MediaPlayer mp, final int what, final int extra) {
                if (interactionListener != null) {
                  final Runnable appCallback =
                      new Runnable() {
                        @Override
                        public void run() {
                          audioPlaybackListener.onAudioPlaybackError(
                              new AudioPlaybackException(
                                  String.format(
                                      Locale.US,
                                      "MediaPlayer error: \"what\": %d, \"extra\":%d",
                                      what,
                                      extra)));
                        }
                      };
                  handler.post(appCallback);
                }
                return false;
              }
            });

        lMediaPlayer.setOnPreparedListener(
            new MediaPlayer.OnPreparedListener() {
              @Override
              public void onPrepared(MediaPlayer mp) {
                if (audioPlaybackListener != null) {
                  final Runnable appCallback =
                      new Runnable() {
                        @Override
                        public void run() {
                          audioPlaybackListener.onAudioPlaybackStarted();
                        }
                      };
                  handler.post(appCallback);
                }
                mp.start();
              }
            });

        lMediaPlayer.setOnCompletionListener(
            new MediaPlayer.OnCompletionListener() {
              @Override
              public void onCompletion(MediaPlayer mp) {
                setAudioPlaybackState(NOT_BUSY);
                if (audioPlaybackListener != null) {
                  final Runnable appCallback =
                      new Runnable() {
                        @Override
                        public void run() {
                          audioPlaybackListener.onAudioPlayBackCompleted();
                        }
                      };
                  handler.post(appCallback);
                }
                try {
                  if (lMediaPlayer.isPlaying() || lMediaPlayer.isLooping()) {
                    lMediaPlayer.stop();
                  }
                  lMediaPlayer.release();
                } catch (final Exception e) {
                  Log.e(TAG, "InteractionClient: Error while releasing MediaPlayer", e);
                } finally {
                  lMediaPlayer = null;
                }
              }
            });

        final InputStream audioStream = result.getAudioStream();
        tempAudioFile = File.createTempFile("lex_temp_response", "dat", context.getFilesDir());
        tempAudioFile.deleteOnExit();
        final FileOutputStream audioOut = new FileOutputStream(tempAudioFile);
        final byte buffer[] = new byte[16384];
        int length;
        while ((length = audioStream.read(buffer)) != -1) {
          audioOut.write(buffer, 0, length);
        }
        audioOut.close();
        final FileInputStream audioIn = new FileInputStream(tempAudioFile);
        lMediaPlayer.setDataSource(audioIn.getFD());
        lMediaPlayer.prepare();
        processResponse(handler, result, client, responseMode, requestType);
      } catch (final Exception e) {
        // Playback failed.
        if (audioPlaybackListener != null) {
          final Runnable appCallback =
              new Runnable() {
                @Override
                public void run() {
                  audioPlaybackListener.onAudioPlaybackError(
                      new LexClientException("Audio playback failed", e));
                }
              };
          handler.post(appCallback);
        }
        try {
          if (lMediaPlayer.isPlaying() || lMediaPlayer.isLooping()) {
            lMediaPlayer.stop();
          }
          lMediaPlayer.release();
          lMediaPlayer = null;
        } catch (final Exception exp) {
          Log.e(TAG, "InteractionClient: Error while releasing MediaPlayer", exp);
        }
        processResponse(handler, result, client, responseMode, requestType);
      } finally {
        setAudioPlaybackState(NOT_BUSY);
      }

    } else {
      processResponse(handler, result, client, responseMode, requestType);
    }
  }