简体   繁体   中英

HttpUrlConnection - Android - Write Output and Read Input in parallel

Dear Android advanced dev :)

I would like to dev an App which record audio from microphone and send registered data to a Speech To Text web service, in real-time transcription mode.

So i need to make a HTTP request and keep this request to continuously send audio data and retrieve , in parallel, the transcription result.

I'm really able to work with the API with a tool like curl but I'm really disappointed not to be able to do it in Java.

You can find a summary of what I try to do in a class. I'm trying to use HttpUrlConnection, I don't know if this is the right approach.

My problem is the following: I can send the audio as it is recorded, however, as soon as I activate the readInputStream method to read the response in parallel, the connection is closed.

The header of the response contains Transfer-Encoding: chunked .

Is there a better way to do this?

Thank you.

/* list of import hidden */

public class RecordAndStream {
    int SAMPLE_RATE = 8000;
    boolean record;
    URL url;
    HttpURLConnection httpURLConnection;
    InputStreamReader inputStreamReader;
    OutputStream outputStream;

    public void readInputStream() {
        try {
            InputStream inputStream = null;
            inputStream = new BufferedInputStream(this.httpURLConnection.getInputStream());
            this.inputStreamReader = new InputStreamReader(inputStream);

            int data = 0;
            data = this.inputStreamReader.read();
            String xml_result = "";
            while (data != -1) {
                xml_result += String.valueOf((char) data);
                data = this.inputStreamReader.read();
            }
            Log.d("LOG", "inputStreamReader=\n" + xml_result);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    public void sendAudioStream() {
        int bufferSize = AudioRecord.getMinBufferSize(this.SAMPLE_RATE,
                AudioFormat.CHANNEL_IN_MONO,
                AudioFormat.ENCODING_PCM_16BIT);

        @SuppressLint("MissingPermission")
        AudioRecord audioRecord = new AudioRecord(MediaRecorder.AudioSource.DEFAULT,
                this.SAMPLE_RATE,
                AudioFormat.CHANNEL_IN_MONO,
                AudioFormat.ENCODING_PCM_16BIT,
                bufferSize);

        audioRecord.startRecording();
        short[] audioBuffer = new short[8192];
        while (this.record) {
            int numberOfShort = audioRecord.read(audioBuffer, 0, audioBuffer.length);
            ByteBuffer bfSTT = ByteBuffer.allocate(numberOfShort * 2);
            bfSTT.order(ByteOrder.LITTLE_ENDIAN);
            for (int z = 0; z < numberOfShort; z++) {
                bfSTT.putShort(audioBuffer[z]);
            }
            try {
                this.outputStream.write(bfSTT.array());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        try {
            this.outputStream.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }

        audioRecord.stop();
        audioRecord.release();

        this.httpURLConnection.disconnect();
    }


    public void stopRecord() {
        this.record = false;
    }

    public void startRecord() {
        this.record = true;
        // declaration d'une url
        try {
            this.url = new URL("https://sercice_url_to_call");
        } catch (MalformedURLException e) {
            Log.e("LOG", "MalformedURLException");
        }
        this.httpURLConnection = null;
        try {
            this.httpURLConnection = (HttpURLConnection) this.url.openConnection();
            this.httpURLConnection.setRequestProperty("Authorization", "Basic " + Base64.encodeToString("xxx:YYY".getBytes(), Base64.NO_WRAP));
            this.httpURLConnection.setUseCaches(false);
            this.httpURLConnection.setRequestMethod("POST");
            this.httpURLConnection.setRequestProperty("Content-Type", "");
            this.httpURLConnection.setRequestProperty("Accept", "*/*");
            this.httpURLConnection.setRequestProperty("Connection", "Keep-Alive");
            this.httpURLConnection.setRequestProperty("Transfer-Encoding", "chunked");
            this.httpURLConnection.setRequestProperty("Expect", "100-continue");
            this.httpURLConnection.setRequestProperty("Accept-Encoding", "gzip");
        } catch (ProtocolException e) {
            Log.e("LOG", "ProtocolException");
        } catch (IOException e) {
            Log.e("LOG", "IOException");
        }

        try {
            //to tell the connection object that we will be wrting some data on the server and then will fetch the output result
            //this.httpURLConnection.setDoOutput(true);
            this.httpURLConnection.setDoOutput(true);
            this.httpURLConnection.setDoInput(true);
            // this is used for just in case we don't know about the data size associated with our request
            this.httpURLConnection.setChunkedStreamingMode(8192);
            // to write tha data in our request
            this.outputStream = new BufferedOutputStream(this.httpURLConnection.getOutputStream());
            // to read the data in the response

            new Thread((new Runnable() {
                protected RecordAndStream ref;

                public Runnable init(RecordAndStream ref) {
                    this.ref = ref;
                    return this;
                }

                @Override
                public void run() {
                    this.ref.readInputStream();
                }
            }).init(this)).start();

            sendAudioStream();

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

After testing several solutions like OkHttp or HttpClient from the Apache foundation, I didn't find any off the shelf solution. So I managed myself the http layer directly in the Buffer of a simple Socket. It works perfectly, I send in stream while receiving in stream.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM