theCNG27
theCNG27

Reputation: 425

Android Datastream between threads

I am trying to implement streaming Audio in my Android app so what I want to do is download the audio file from an http server in one thread and send it to the second thread for decoding. To send the stream from the first to the second thread I have tried using different types of BlockingQueues and even PipedReader and PipedWriter (but those were very, very slow). To test the communication between threads I just write the data to a file in the second thread instead of decoding the mp3 data.

The two threads are spawned by the Main Thread (The download thread is actually an AsyncTask).

This is the Queue, created final in Main Thread: final BlockingQueue stream = new LinkedBlockingQueue();

doInBackground() of AsyncTask:

                InputStream input = null;
                HttpURLConnection connection = null;
                try {
                    URL url = new URL("http://" + serverIP + "/songs/test.mp3");
                    connection = (HttpURLConnection) url.openConnection();
                    connection.connect();
                    int fileLength = connection.getContentLength();
                    input = connection.getInputStream();

                    byte data[] = new byte[CHUNK_SIZE];
                    long total = 0;
                    int count;
                    while ((count = input.read(data)) != -1) {
                        total += count;
                        stream.put(new StreamBuffer(data, count));
                    }

                } catch (Exception e) {
                    return -1;
                } finally {
                    try {
                        if (output != null) output.close();
                        if (input != null) input.close();
                    } catch (Exception e) {
                    }

                    if (connection != null)
                        connection.disconnect();
                }

run() of Thread 2:

        try {
            FileOutputStream outputnf = null;
            try {
                outputnf = new FileOutputStream(Environment.getExternalStorageDirectory() + "/CCMP/test.mp3");
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }

            while (true) {
                StreamBuffer buff = ((StreamBuffer) stream.take());
                if (outputnf != null) {
                    outputnf.write(buff.buffer, 0, buff.length);
                }
            }
        } catch (Exception e) {
            System.out.println(" PipeThread Exception: " + e);
        }

StreamBuffer:

public class StreamBuffer
{
    byte[] buffer;
    int length;

    public StreamBuffer(byte[] data, int count) {
        buffer = data;
        length = count;
    }
}

The data is downloaded correctly but when I look into the file, it is corrupted (some parts are missing or just wrong). Whats wrong with the code? Is it even possible to stream a whole file between threads without "loss"? Shouldn't it be? Should I reconsider the structure of my program? Maybe put everything in one thread? Thanks in advance...

Upvotes: 0

Views: 186

Answers (2)

theCNG27
theCNG27

Reputation: 425

Ok so I solved this myself. The problem was, how lbalazscs suggested, that all StreamBuffer elements were using the same byte[] array. So this was the solution to my problem:

public class StreamBuffer
{
    byte[] buffer;

    public StreamBuffer(byte[] data, int count) {
        buffer = new byte[count];
        System.arraycopy(data, 0, buffer, 0, count);
    }
}

Upvotes: 0

lbalazscs
lbalazscs

Reputation: 17784

  1. The threading part of the code seems OK
  2. Yes, it should be possible to pass an arbitrary amount of data between threads
  3. You could implement temporarily a single-threaded code just to filter out the possibility of other bugs. You could have a FileWriter interface with an asynchronous and a synchronous implementation.
  4. I don't know what a StreamBuffer is, but I don't like the fact that different StreamBuffer objects share the same data array. There could be a bug around this code.

Upvotes: 1

Related Questions