How to receive socket correctly - android

I'm trying to send the pictures between two android devices, but there is a transmission problem I can't figure out. Someone tell me to revise the wile loop, but it still do not work.
When I tested my project on the device, there wasn't problem with the connection. But, as the transmission task started, the sending client was stopped and "transfer erro" msg showed up on the receiver.
Is there anyone knows what can I do to my program? Here are my two mainly parts of sending and receiving.
I'll be very appreciative of any help. Thank you.
sending part:
s = new Socket("192.168.0.187", 1234);
Log.d("Tag====================","socket ip="+s);
File file = new File("/sdcard/DCIM/Pic/img1.jpg");
FileInputStream fis = new FileInputStream(file);
din = new DataInputStream(new BufferedInputStream(fis));
dout = new DataOutputStream(s.getOutputStream());
dout.writeUTF(String.valueOf(file.length()));
byte[] buffer = new byte[1024];
int len = 0;
while ((len = din.read(buffer)) != -1) {
dout.write(buffer, 0, len);
tw4.setText("8 in while dout.write(buffer, 0, len);");
}
dout.flush();
the sending part can work smoothly and no erro showed up after the while loop overed
receiving part:
try {
File file = new File("/sdcard/DCIM/img1.jpg");
DataInputStream din = new DataInputStream(new BufferedInputStream(client.getInputStream()));
bis = new BufferedInputStream(client.getInputStream());
Log.d("Tag====================","din="+s);
FileOutputStream fos = new FileOutputStream(file);
dout = new DataOutputStream(new BufferedOutputStream(fos));
byte[] buffer = new byte[1024];
int len = 0;
while ((len = bis.read(buffer)) != -1) {
dout.write(buffer, 0, len);
}
dout.flush();
dout.close();
} catch (Exception e) {
handler.post(new Runnable() {
public void run() {
tw1.setText("transmission error");
}});
About the receiving part seems even stuck at the "DataInputStream din = new DataInputStream(new BufferedInputStream(client.getInputStream()));" and catch the exception.
Thanks again.

You're writing the file length with writeUTF() but you're never reading it. If you're going to close the socket after sending the image, you don't need the length: just send and then close the socket. If you do need the length, read it, with readUTF(), and then read exactly that many bytes from the socket to the target.
And if you need the length it would make more sense to send it with writeInt() or writeLong() than to convert the number to a string, convert that to writeUTF() format, convert that back to a string at the other end with readUTF(), and then convert that back to an int or a long. That also implies using readInt() or readLong() as appropriate, of course.
EDIT
For about the millionth time (wish I had a $ for each time), the canonical way to copy a stream in Java is:
while ((count = in.read(buffer)) > 0)
{
out.write(buffer, 0, count);
}
where 'count' is an int and 'buffer' is a byte array with length > 0, preferably 8192 or more. Note that you have to loop; you have to store the read() result in a variable; you have to test that variable; and you have to use it in the write() call.

Related

Writing an audio file to websocket using IBM Watson Android sdk

I realized after going through a post in the IBM developer forums that the android sdk reads bytes from the mic recording and writes them to the websocket. I am now trying to read bytes from an audio file on memory and write them to the websocket. How should I do this? So far I have:
public class AudioCaptureThread extends Thread{
private static final String TAG = "AudioCaptureThread";
private boolean mStop = false;
private boolean mStopped = false;
private int mSamplingRate = -1;
private IAudioConsumer mIAudioConsumer = null;
// the thread receives high priority because it needs to do real time audio capture
// THREAD_PRIORITY_URGENT_AUDIO = "Standard priority of the most important audio threads"
public AudioCaptureThread(int iSamplingRate, IAudioConsumer IAudioConsumer) {
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);
mSamplingRate = iSamplingRate;
mIAudioConsumer = IAudioConsumer;
}
// once the thread is started it runs nonstop until it is stopped from the outside
#Override
public void run() {
File path = Activity.getContext.getExternalFilesDir(null);
File file = new File (path, "whatstheweatherlike.wav");
int length = (int) file.length();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] b = new byte[length];
FileInputStream in = null;
try {
in = new FileInputStream(file);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
try {
for (int readNum; (readNum = in.read(b)) != -1;) {
bos.write(b, 0, readNum);
}
} catch (IOException e) {
e.printStackTrace();
}
byte[] bytes = bos.toByteArray();
mIAudioConsumer.consume(bytes);
}
However, Activity.getContext is not recognized. I can convert the file to bytes in MainActivity but how do I then write it to the websocket? Am I on the right track or is this not the right way? If it is, how do I solve this problem?
Any help is appreciated!
Activity.getContext is not recognized because there's no reference to Activity, since it's just a Thread. You would have to pass in the Activity, although it would likely make more sense just to pass in the Context if you need it.
You've got the right idea that you can create a FileInputStream and use that. You might like to use our MicrophoneCaptureThread as a reference. It'd be a very similar situation, except you'd be using your FileInputStream instead of reading from the microphone. You can check it out (and an example project that uses it) here: https://github.com/watson-developer-cloud/android-sdk/blob/master/library/src/main/java/com/ibm/watson/developer_cloud/android/library/audio/MicrophoneCaptureThread.java

android 5.0.1 file upload not throwing exception when network is lost

I have an Android intentservice for uploading files to server. The files will be added to the intentservice queue for every 1 min.It is working fine in the android devices with OS less than 5.0.1. But in android 5.0.1 while uploading the file, if network is lost, I am not getting any response, not throwing any exception and the intent service is blocked. Files are not uploading from that point. I have to restart the app in order to make the service work again. Below is the code I have in onHandleIntent method.
int ReadBytes = 0;
int BUFSIZ = 4096;
byte Buf[] = new byte[BUFSIZ];
outputStream = conn.getOutputStream();
dataOutputStream = new DataOutputStream(outputStream);
fileInputStream = new FileInputStream(source);
long prevBytesRead = 0;
ReadBytes = fileInputStream.read(Buf, 0, BUFSIZ);
while(ReadBytes>0){
dataOutputStream.write(Buf, 0, ReadBytes);
prevBytesRead += ReadBytes;
long totalbytes = fileInputStream.getChannel().size();
ReadBytes = fileInputStream.read(Buf, 0, BUFSIZ);
}
outputStream.flush();
dataOutputStream.flush();
Any help would be appreciated.
You are probably leaking the stream, you should try wrapping it in a try/catch block:
try {
int ReadBytes = 0;
int BUFSIZ = 4096;
byte Buf[] = new byte[BUFSIZ];
outputStream = conn.getOutputStream();
dataOutputStream = new DataOutputStream(outputStream);
fileInputStream = new FileInputStream(source);
long prevBytesRead = 0;
ReadBytes = fileInputStream.read(Buf, 0, BUFSIZ);
while(ReadBytes>0){
dataOutputStream.write(Buf, 0, ReadBytes);
prevBytesRead += ReadBytes;
long totalbytes = fileInputStream.getChannel().size();
ReadBytes = fileInputStream.read(Buf, 0, BUFSIZ);
}
outputStream.flush();
dataOutputStream.flush();
} catch (IOException e) {
} finally {
// Close streams with an additional try/catch
}
Perhaps you should take a look at Facebook's infer tool: fbinfer.com , very useful for these situations.

Android client / server, client not receiving all data

I have probably been staring at this too long and can't see what the problem is.
I have a server which accepts multiple client connections and saves the sockets. The server can then send out control messages to the clients to perform tasks and, among other things, I want to send files out to all the connected clients but the client only seems to receive part of them.
For testing purposes I have a randomly generated text file 69075 bytes but although it seems like whole whole file is sent, the client only receives upto around 57000 bytes (varies). I have added a button on the server app which lets me close the client socket and when I do that the client receives -1 followed by the rest of the missing file.
Server sending file:
try {
getClientList().get(0).setLocked(true);
byte [] mybytearray = new byte [1024];
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(myFile));
OutputStream os = getClientList().get(0).getmSocket().getOutputStream();
Boolean eof = false;
int bytesRead;
int total = 0;
do {
bytesRead = bis.read(mybytearray, 0, mybytearray.length);
if (bytesRead != -1) {
os.write(mybytearray, 0, bytesRead);
total += bytesRead;
Log.d(TAG_SF, "Total: "+total+" :Sent: "+ bytesRead);
} else {
eof = true;
Log.d(TAG_SF, "EOF, Total sent: " + total);
}
} while (!eof);
os.flush();
bis.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
getClientList().get(0).setLocked(false);
}
A message is sent to the clients with the file name and file size before the file is send and it is received ok.
Client receiving file:
try {
int total = 0;
byte[] myByteArray = new byte[1024];
int bytesRead;
InputStream is = serverSocket.getInputStream();
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream(path+SD_DIRECTORY+fileName));
do {
bytesRead = is.read(myByteArray, 0, myByteArray.length);
if (bytesRead != -1){
bos.write(myByteArray, 0, bytesRead);
total = total+bytesRead;
Log.e(TAG,"Total > "+total+ ": No Bytes : "+bytesRead);
} else {
Log.e(TAG,"EOF, total received: "+total);
break;
}
} while (total < fileLength); //fileLength and filename are sent before file
Log.e(TAG,"Total > "+total+ ": No Bytes : "+bytesRead);
bos.flush();
bos.close();
} catch (Exception e) {
e.printStackTrace();
}
The problem was not with the code for sending and receiving, it works fine.
I was sending a message to the client first with a control code indicating a file was to be send, followed by the file size and file name. The client then waits for the file but the server started sending before the client was ready and was missing the start of the file.
To test, put the server thread to sleep for a couple of seconds after sending the file name and before sending the file and it works fine. I will probably have the client send a 'ready' message to the server as a better solution.
EDIT:
Although this worked, it is not the answer, it does seem to be related to using both buffered and unbuffered streams (see EJP comment). Will do a bit of re writing and update accordingly. Not sure of SO protocol, should I delete a wrong answer?
EDIT (again)
EJPs comment is absolutely correct, it was related to having a buffered input stream open to receive the file name and then opening an unbuffered stream elsewhere to transfer the file. My knowledge is limited in this area (and generally) so I just re wrote to use the same unbuffered stream for both.

download multiple subsequent files from one server with one TCP handshake

I try to create an application that can download files from a server in order to measure the speed that I can get with the particular server. I do this by using the Asynctask class. All the files that I want to download are located on the same directory. My question is, how can I download the subsequent files by keeping the connection and not by creating every time a new one? I know that for a TCP connection, there must be a 3-way-handshake established, before downloading a file. I want to connect to the server and then keep the connection and perform the download.
My code looks like this
#Override
protected Integer doInBackground(String... sUrl) {
try {
speed=0; //initial value
int i=0;
while ((i<sUrl.length)) {
URL url = new URL(sUrl[i]); //sUrl[] contains the links that i want
// for example http://myserver.net/file1.jpg, http://myserver.net/file2.jpg ... etc
URLConnection connection = url.openConnection();
connection.connect(); //connection to be established 3WAY HANDSHAKE
int fileLength = connection.getContentLength();
// download the file
InputStream input = new BufferedInputStream(url.openStream());
OutputStream output = new FileOutputStream(file);
byte data[] = new byte[1024];
long total = 0;
int count;
long start = System.currentTimeMillis();
while ((count = input.read(data)) != -1) {
total += count;
publishProgress((int) (total * 100 / fileLength));
output.write(data, 0, count);
}
long finish = System.currentTimeMillis();
long tempSpeed= (fileLength *8)/(finish-start);
if (tempSpeed>speed) {
speed=tempSpeed;
}
output.flush();
output.close();
input.close(); // connection is closed
i++;
}
}catch(Exception e) {
exceptions.add(e);
}
return 1;
}
By creating a new connection I loose time (for the download speed), because of the 3way handsharke . Also when transfering files in TCP, there is something called a tcp window (when you dowload data, initialy you start with low speed transmission, and if the connection is good this rate increases).
How can I do the above without creating and tearing down the connection for each file?
Looking at you code, you keep receiving until the socket is close at the other side, so there is no way of using the same socket since it's closed. If you can program both, the server and the client, then, I would suggest one possible way of doing it, and that is with a protocol, instead of receiving the file directly, the first packet you get is an integer which indicates the size of the file you're going to receive. If that length is 0 (cero) it means there no more files and the connection should be closed.
At the server:
While (the_are_files_to_send)
{
Socket.write((int) FileSize);
Socket.write(file's content);
}
Socket.Write(0); // No more files;
Socket.Close();
At the Client:
While ((size = Socket.read(buffer, 0, 4)) != -1)
{
int FileLength = convert_to _int(buffer);
if (FileLength==0) break;
Socket.read(FileLength bytes);
}
Socket.Close();

Bluetooth comunication android

I need to pass an Intent by bluetooth. Peviously I created the game and I save the caracteristics of the game in a class type singleton.
What I want to do is pass this information to the other device that I'm already connected and start de game that previously me or he/she created.
How can I send this information and the activity of the game?
I use andengine to make all the game.
Thanks!
I think this site may help you. There are a few methods, but you want the last one mentioned in the OP.
public void sendFile(Uri uri, BluetoothSocket bs) throws IOException {
BufferedInputStream bis = new BufferedInputStream(getContentResolver().openInputStream(uri));
OutputStream os = bs.getOutputStream();
try {
int bufferSize = 1024;
byte[] buffer = new byte[bufferSize];
// we need to know how may bytes were read to write them to the byteBuffer
int len = 0;
while ((len = bis.read(buffer)) != -1) {
os.write(buffer, 0, len);
}
} finally {
bis.close();
os.flush();
os.close();
bs.close();
}
}
Hope this helps.

Categories

Resources