Android DataOutputStream Flush method does not seem to actually flush - android

Here's some quick code I am doing. (I removed some of it to make it more readable.) Essentially, I'm opening a file, and processing 3k chunks at a time. These get encoded to Base64 (4k chunk now) and uploaded via HTTP post. After each call to DataOutputStream.writeBytes() I also call DataOutputStream.flush() and then I update a progress bar based on how much has been sent.
File myImage = new File(somepath);
int bytesAvailable = myImage.length();
while (bytesAvailable > 0)
{
byte[] buffer = new byte[Math.min(12288, (int)bytesAvailable)];
bytesRead = fileInputStream.read(buffer, 0, Math.min(12288, (int)bytesAvailable));
if (bytesRead > 0)
{
s2 = Base64.encodeBytes(buffer);
bytesAvailable = fileInputStream.available();
dataStream.writeBytes(s2);
dataStream.flush();
// UPDATE THE PROGRESS BAR HERE
}
}
Now, when I run the application, the image is successfully uploaded each time. However if I watch the mobile connection indicator (up/down arrows), they do not light up while the progress bar moves. The bar will go from 0 to 100% over the course of 10 seconds or so for a 3MB image (far too fast for my 3G phone). Then at 100%, after this loop is done, the dataStream.close() method is called. This is when the data transmission starts (as indicated by the arrows). This sits for a few minutes before finishing.
Am I not understanding flush() correctly? Shouldn't it force data to be transmitted?

It sounds to me like you're adding 4k chunks into a data stream and then sending that data stream in a http post to a server. If this is the case, then your loop is essentially iterating over a memory copy, and the http transfer will happen after you finish with the data stream. The only way to know for sure how the upload is going will be to get your hands on the socket and its data stream. This looks quite difficult if your using DefaultHttpClientConnection and so on.

Related

Bluetooth - Output Stream

I have connected an arduino with my android device and I have set up the connection and obtained Output Stream.
ANDROID PART
String one = "1";
byte[] input = one.getBytes(Charset.forName("UTF-8"));
mConnectedThread.write(input);
ARDUINO PART
How can I process the received byte[] and convert it back to String?
There is a 128byte buffer on the incoming stream. Use
In your loop():
char inByte;
// check for bytes in the buffer
if (Serial.available() > 0) {
// read the available bytes one at a
// time and purge from buffer
inByte = Serial.read();
// print out byte so you can see it on
// the serial monitor
Serial.print(inByte);
}
If the buffer is big enough for your needs then you won't need to worry about coding anything else. You can deal with the incoming bytes in a char array or read the individual chars into a String object.
There is lots of good information here:
http://arduino.cc/en/Reference/string
...on char arrays and a link at the top of that page to the String object. Let me know if you have further questions, hopefully this gets you at least started and debugging the incoming code correctly

InputStream reads available data in more than 1 try

I have two applications. Connected to each other over wifi. I am using InputStream to read data sent from server app.
The code is std one,
try {
bytesRead = mmInStream.read(buffer, 0, 6300);//read(buffer);
Logger.d(TAG, "Bytes read from inStream : "+bytesRead);
if (-1 != bytesRead) {
handler.obtainMessage(12, bytesRead, -1, buffer).sendToTarget();
} else {
connectionLost();
}
} catch (Exception e) {
e.printStackTrace();
connectionLost();
}
Killing and resetting threads in connectionLost method.
I am sending close to 6kb data from server app, in a JSON String.
This works 3 out of 5 times.
Sometimes the read will return say, 1.5kb buffer and in second run it will give rest of data. But meanwhile first 1.5 is sent to JSON parser and that gives me error.
I printed bytes written to outputBuffer from server side. it will write 6k bytes every time. I want to know why at sometime, read() method reads only half of stream and rest of it in second try?
How do i know if it has read total data or only half of it?
i dont know before hand how many bytes server will send. (I came up with number because i am debugging the code. that 6k may change later).
Thank you in advance. Stuck at this issue for two days. :(
It works as designed. When you read a stream, you are not guaranteed to get all available bytes in one go. Most likely they are not even available when you do the first read.
You need some programmatic ways to find out if a message is complete. For example if it is a JSON object or array, you will notice if it is complete or not by analysing what you got. Another way would be to transmit the length of the message.

Mono for Android - Activity crash upon service call

My application has a UI (implemented with an Activity) and a service (implemented with the IntentService). The service is used to send data (synchronous, using NetworkStream.Write) to a remote server as well as to update the transmission status to the UI (implemented using Broadcast Receiver method).
Here is my problem:
The application works properly if the size of the buffer used for the NetworkStream.Write is 11 KB or less.
However, if the size of the buffer is larger than 11 KB, say 20 KB (this size needed in order to send jpg images), then the sevice keeps working properly (verified with log file), nonetheless the UI its gone (similar as if device's back button is pushed) and I can't find the way to bring it back. Its important to point out that in this case the Activity its not going into OnStop() nor OnDestroy() states.
At first I thought this would be some ApplicationNotResponding related issue due to a server delay, yet the UI crashes after about 5 sec.
Moreover, this only happens with the Hardware version. The emulator version works fine.
// SEND STREAM:
Byte[] outStream = new Byte[20000];
// -- Set up TCP connection: --
TcpClient ClientSock = new TcpClient();
ClientSock.Connect("myserver.com", 5555);
NetworkStream serverStream = ClientSock.GetStream();
serverStream.Write(outStream, 0, outStream.Length);
serverStream.Flush();
// . . .
// RECEIVE STREAM:
inStream.Initialize(); // Clears any previous value.
int nBytesRead = 0;
nBytesRead = serverStream.Read(inStream, 0, 1024);
// -- Closing communications socket: --
ClientSock.Close();
One thing first: I would have been commented the question to clarify one thing before I give an answer, but unfortunately I don't have enough reputation yet.
The thing I would have asked for is: Why do you need to have a buffer greater than 11k to send an JPG image?
I nearly do the same in one (async) task with an image of 260k, but with a buffer of 10240 Bytes. Works without difficulties.
byte[] buffer = new byte[10240];
for (int length = 0; (length = in.read(buffer)) > 0;) {
outputStream.write(buffer, 0, length);
outputStream.flush();
bytesWritten += length;
progress = (int) ((double) bytesWritten * 100 / totalBytes);
publishProgress();
}
outputStream.flush();
I use this part to read an JPG image from resources or SD and post to my server.
Well you may want to change your application to use asynctask and take a look to the guide :
http://developer.android.com/training/basics/network-ops/connecting.html
Network operations can involve unpredictable delays. To prevent this from causing a poor user experience, always perform network operations on a separate thread from the UI.
Since android 4.0 it's impossible to perform network related task in the same thread as the UI thread. Also just to be clear http://developer.android.com/guide/components/services.html
Caution: A service runs in the main thread of its hosting process—the
service does not create its own thread and does not run in a separate
process

android - Bluetooth: program stuck at inputstream reading

Helo.
Im developing an application that transferes data over bluetooth(with a flight recorder device). When i am recieving a lot of data data(3000 - 40000 lines of text, depends of the file size) my aplication seems to stop recieving the data. I recieve the data with InputStream.read(buffer). For example: I send a command to the flight recorder, it starts sending me a file(line by line), on my phone i recieve 120 lines and then the app stucks.
Intresting is that on my HTC Desire the app stucks just sometimes, on the Samsung Galaxy S phone the application stucks every single time i try to recive more than 50 lines.
The code is based on the BluetoothChat example. This is the part of code where i am listening to the BluetoothSocket:
byte[] buffer = new byte[1024];
int bytes =0;
while(true)
{
bytes = mmInStream.read(buffer);
readMessage = new String(buffer, 0, bytes);
Log.e("read", readMessage);
String read2 = readMessage;
//searching for the end of line to count the lines(the star means the start of the checksum)
int currentHits = read2.replaceAll("[^*]","").length();
nmbrOfTransferedFligts += currentHits;
.
.
.
//parsing and saving the recieved data
I must say that i am running this in a while(true) loop, in a Thread, that is implemented in an android Service. The app seems to stuck at "bytes = mmInStream.read(buffer);"
I have tried to do this with BufferedReader, but with no success.
Thanks.
The app seems to stuck at "bytes = mmInStream.read(buffer);"
But that is normal behavior: InputStream.read(byte[]) blocks when there is no more data available.
This suggests to me that the problem is on the other end or in the communication between the devices. Is is possible that you have a communication problem (which is a bit different on the Galaxy vs. the Desire) that is preventing more data from being received?
Also, I would suggest that you wrap a try/catch around the read statement to be sure that you catch any possible IOException's. Though I guess you would have seen it in logcat if that were happening.
Speaking of logcat, I would suggest that you look at the logcat statements that Android itself it generating. I find that it generates a lot for Bluetooth and this might help you to figure out whether there really is any more data to be read().

AudioTrack: Playing sound coming in over WiFi

I've got an AudioTrack in my application, which is set to Stream mode. I want to write audio which I receive over a wireless connection. The AudioTrack is declared like this:
mPlayer = new AudioTrack(STREAM_TYPE,
FREQUENCY,
CHANNEL_CONFIG_OUT,
AUDIO_ENCODING,
PLAYER_CAPACITY,
PLAY_MODE);
Where the parameters are defined like:
private static final int FREQUENCY = 8000,
CHANNEL_CONFIG_OUT = AudioFormat.CHANNEL_OUT_MONO,
AUDIO_ENCODING = AudioFormat.ENCODING_PCM_16BIT,
PLAYER_CAPACITY = 2048,
STREAM_TYPE = AudioManager.STREAM_MUSIC,
PLAY_MODE = AudioTrack.MODE_STREAM;
However, when I write data to the AudioTrack with write(), it will play choppy... The call
byte[] audio = packet.getData();
mPlayer.write(audio, 0, audio.length);
is made whenever a packet is received over the network connection. Does anybody have an idea on why it sounds choppy? Maybe it has something to do with the WiFi connection itself? I don't think so, as the sound doesn't sound horrible the other way around, when I send data from the Android phone to another source over UDP. The sound then sounds complete and not choppy at all... So does anybody have an idea on why this is happening?
Do you know how many bytes per second you are recieving, the average time between packets compares, and the maximum time between packets? If not, can you add code to calculate it?
You need to be averaging 8000 samples/second * 2 bytes/sample = 16,000 bytes per second in order to keep the stream filled.
A gap of more than 2048 bytes / (16000 bytes/second) = 128 milliseconds between incoming packets will cause your stream to run dry and the audio to stutter.
One way to prevent it is to increase the buffer size (PLAYER_CAPACITY). A larger buffer will be more able to handle variation in the incoming packet size and rate. The cost of the extra stability is a larger delay in starting playback while you wait for the buffer to initially fill.
I have partially solved it by placing the mPlayer.write(audio, 0, audio.length); in it's own Thread. This does take away some of the choppy-ness (due to the fact that write is a blocking call), but it still sounds choppy after a good second or 2. It still has a significant delay of 2-3 seconds.
new Thread(){
public void run(){
byte[] audio = packet.getData();
mPlayer.write(audio, 0, audio.length);
}
}.start();
Just a little anonymous Thread that does the writing now...
Anybody have an idea on how to solve this issue?
Edit:
After some further checking and debugging, I've noticed that this is an issue with obtainBuffer.
I've looked at the java code of the AudioTrack and the C++ code of AudioTrack And I've noticed that it only can appear in the C++ code.
if (__builtin_expect(result!=NO_ERROR, false)) {
LOGW( "obtainBuffer timed out (is the CPU pegged?) "
"user=%08x, server=%08x", u, s);
mAudioTrack->start(); // FIXME: Wake up audioflinger
timeout = 1;
}
I've noticed that there is a FIXME in this piece of code. :< But anyway, could anybody explain how this C++ code works? I've had some experience with it, but it was never as complicated as this...
Edit 2:
I've tried somewhat different now, the difference being that I buffer the data I receive, and then when the buffer is filled with some data, it is being written to the player. However, the player keeps up with consuming for a few cycles, then the obtainBuffer timed out (is the CPU pegged?) warning kicks in, and there is no data at all written to the player untill it is kick started back to life... After that, it will continually get data written to it untill the buffer is emptied.
Another slight difference is that I stream a file to the player now. That is, reading it in chunks, the writing those chunks to the buffer. This simulates the packages being received over wifi...
I am beginning to wonder if this is just an OS issue that Android has, and it isn't something I can solve on my own... Anybody got any ideas on that?
Edit 3:
I've done more testing, but this doesn't help me any further. This test shows me that I only get lag when I try to write to the AudioTrack for the first time. This takes somewhat between 1 and 3 seconds to complete. I did this by using the following bit of code:
long beforeTime = Utilities.getCurrentTimeMillis(), afterTime = 0;
mPlayer.write(data, 0, data.length);
afterTime = Utilities.getCurrentTimeMillis();
Log.e("WriteToPlayerThread", "Writing a package took " + (afterTime - beforeTime) + " milliseconds");
However, I get the following results:
Logcat Image http://img810.imageshack.us/img810/3453/logcatimage.png
These show that the lag initially occurs at the beginning, after which the AudioTrack keeps getting data continuously... I really need to get this one fixed...

Categories

Resources