How to use Socket, ObjectInputStream and ObjectOutputStream in Android? [duplicate] - android

My problem is when it tries to read the object the second time, it throws the exception:
java.io.StreamCorruptedException: invalid type code: AC
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1356)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:351)
at Client.run(BaseStaInstance.java:313)
java.io.StreamCorruptedException: invalid type code: AC
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1356)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:351)
at Client.run(BaseStaInstance.java:313)
The first time I send the exact same object message; however, when I try doing the same thing the second time, it throws the error above. Do I need to re-intialize the readObject() method? I even printed out the message object that is being received by the line below and its exact the same as the first instance where it works ok.
Object buf = myInput.readObject();
I'm assuming there's some problem with appending, but I really have no use for appending. I just want to read a fresh line everytime.
I'd really appreciate some help in fixing this bug. Thank you.
==================================
Before that one line, I'm just creating the input and output objects for the socket in the run() method. The object declaration is outside the run() method in the class:-
#Override
public void run() {
try {
sleep((int) 1 * 8000);
} catch (Exception e) {
e.printStackTrace();
}
try {
//Creating input and output streams to transfer messages to the server
myOutput = new ObjectOutputStream(skt.getOutputStream());
myInput = new ObjectInputStream(skt.getInputStream());
while (true) {
buf = myInput.readObject();
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
} catch (Exception e) {
e.printStackTrace();
}
}
}
You're right; I don't close the object. I'm not sure how to do that.

The underlying problem is that you are using a new ObjectOutputStream to write to a stream that you have already used a prior ObjectOutputStream to write to. These streams have headers which are written and read by the respective constructors, so if you create another ObjectOutputStream you will write a new header, which starts with - guess what? - 0xAC, and the existing ObjectInputStream isn't expecting another header at this point so it barfs.
In the Java Forums thread cited by #trashgod, I should have left out the part about 'anew for each object at both ends': that's just wasteful. Use a single OOS and OIS for the life of the socket, and don't use any other streams on the socket.
If you want to forget what you've written, use ObjectOutputStream.reset().
And don't use any other streams or Readers or Writers on the same socket. The object stream APIs can handle all Java primitive datatypes and all Serializable classes.

Related

Why the function using socket to transfer data makes my activity crash?

I am now using a function to transfer data to the server. The function uses socket to transfer data. However, when I use this function in my activity, it makes this activity crash and jumps to the prior activity. I wonder why this happened?
public void transferdata(float[] a){
Socket socket;
try{
socket=new Socket("192.168.86.2",1989);
OutputStream outputstream=socket.getOutputStream();
byte[] b=floatToByte(a);
outputstream.write(b,0,0);
outputstream.flush();
}
catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private void touchEventHandler(float touchpoint_X, float touchpoint_Y){
float []a=new float[2];
transferdata(a);
}
If you catch a general Exception and see its message, you will see it is NetworkOnMainThreadException.
Network operation must be done in Java concurrent or Kotlin coroutine, in old versions you can use AsyncTask.

why using DecodeStream(stream) take longer time in a thread than it is in main thread?

I am trying to receive image stream from desktop in the android phone. When I put decodeStream() method in my thread, then put decodestream() into runOnuiThread() to display in the imageView, it takes more than 7 secs. But when I try to directly read image from asset, and convert into inputstream, then decodeStream(), it may take 500ms, I don't know why it happens. The image is 100K.
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
SocketConnect = new socketConnect();
SocketConnect.connectsocket("134.129.125.126", 8080);
while (true) {
data = new byte[2048 * 2048];
try {
read = SocketConnect.getInputStream().read(data, 0,
data.length);
input = SocketConnect.getInputStream();
System.out.println("getInputStream()");
bitmap = BitmapFactory.decodeStream(input);
System.out.println("decodestream()");
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
System.out.println(e);
}
runOnUiThread(new Runnable() {
public void run() {
image.setImageBitmap(bitmap);
System.out.println("setImage at less than 500");
}
});
}
}
});
thread.start();
client side should sent the image very 5 sec.
If I try to read same image from asset, Image display immedately.
try {
inputasset=getAssets().open("good1.jpg");
Bitmap bit = BitmapFactory.decodeStream(inputasset);
image.setImageBitmap(bit);
} catch (IOException e) {
TODO Auto-generated catch block
e.printStackTrace();
}
socketConnect class
public class socketConnect {
private Socket clientSocket;
private InputStream input;
private Bitmap bMap;
public InputStream getInputStream() {
return input;
}
public void connectsocket(String ipString, int port)
{
System.out.println("starts");
try {
// clientSocket = new Socket("134.129.125.172",8080);
System.out.println("starts");
clientSocket = new Socket(ipString, port);
System.out.println("AsyncTask: Connect to 134.129.125.126");
input = clientSocket.getInputStream();
System.out.println("AsyncTask: get the inputStream");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
read = SocketConnect.getInputStream().read(data, 0,
data.length);
input = SocketConnect.getInputStream();
System.out.println("getInputStream()");
bitmap = BitmapFactory.decodeStream(input);
System.out.println("decodestream()");
You read the data from the input stream, then you ask the BitmapFactory to read the data from the input stream. But you already read it! Remove the call to read -- you're stealing data from the BitmapFactory.
My guess would be that the server side is not properly signaling that the end of the file has been reached. I've encountered this previously because the web server implementation might not tell you the length of the file it is sending. If it doesn't set the content length then the input stream keeps trying to read forever. My guess is that it takes a number of minutes because this is the default socket timeout value.
So, the input stream from the socket reads as much as it can and keeps waiting for more data. After waiting several minutes (although usually 5 minutes is the default timeout) the socket closes and you get your image.
I'm not entirely sure that a content length will help, another option might be that the server closes the connection after all the data is sent.
Clearly, if you're trying to stream new images though, you need to do something different than you are. Perhaps have your server send a file header that the reader interprets. This header might include the length of the data being sent and then the client you write stops reading after reaching this length. In this case you'll need to read the image data into a buffer and then have the BitmapFactory read the buffer instead of the stream.
An alternate approach would have the server close the connection after sending the data for each image and then the client would reconnect to get the next one.
Bottom line, not all InputStreams are created equal and a SocketInputStream doesn't know when to close without a content length or the socket being closed.

InputStream receives incomplete data

I am using a Socket connection to connect to a database. When I pull data from the database via InputStream, sometimes it returns full data but most of the time it returns incomplete data (5%/95%). There's an EOF that the database sends but it only gets that far about 5% of the time.
#Override
protected Socket doInBackground(Void... params) {
Socket client = null;
try {
client = new Socket(SocketHelper.IP_ADDRESS, SocketHelper.PORT);
//output message
OutputStream output = client.getOutputStream();
output.write(message.getBytes("UTF-8"));
//parse response
//blocks here more of the time
SocketHelper.parseData(client.getInputStream());
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return client;
}
In my parse method, I look for the EOF and would normally close the InputStream and close the Socket there. I can't find any consistencies for the times it does reach the EOF. Right now the length of the data is static, I haven't adjusted it while I"m trying to figure this out. But the length of the data will be dynamic.
To read data from a Socket, in your parseData method you need to loop, calling read(byte[] b, int off, int len) until all the bytes you expect have arrived.
The read method returns the number of bytes actually read; keep looping until you've got everything. Remember to adjust the offset argument, so that you build up the full message.

Android asynctask reading from socket

Im having some trouble reading/writing to a tcp server for which im building an app. In a recent thread I was suggested to use a service instead but this is a project for school which suggested asyncTask so I might aswell go for that.
So the classes ive got are my activity class and async, nothing interesting is going on in activity but sending a string which is working so ill get on with the async one.
class ServerTask extends AsyncTask<Void, Void, Void>{
public static String ip = "10.0.2.2";
public static int port = 2002;
Socket socket;
public DataInputStream dis;
public DataOutputStream dos;
public String message;
#Override
protected Void doInBackground(Void... params) {
try {
socket = new Socket(ip, port);
dis = new DataInputStream(socket.getInputStream());
dos = new DataOutputStream(socket.getOutputStream());
} catch (Exception e) {
Log.i("AsyncTank", "Cannot create Socket");
}
while(socket.isConnected()){
read();
}
}
}
return null;
}
public void write(String message) {
try {
if (socket.isConnected()){
dos.writeUTF(message);
dos.flush();
} else {
Log.i("AsynkTask", "Socket appears to be closed");
}
} catch (Exception e) {
Log.i("AsynkTask", "Writing failed");
}
}
public String read() {
try {
if (socket.isConnected()) {
message = dis.readLine();
} else {
Log.i("AsyncTask", "Cannot read");
}
} catch (Exception e) {
Log.i("AsyncTask", "Cannot read from stream");
}
return message;
}
}
Things I do know, the server DOES get the messages but it doesnt update until I restart the server which leads me to believe that im not pushing a new line or something which makes it all appear as one line after its closed. This however might aswell be the server for which im not reponsible so ill have to read up in that.
The read part however does not want to work, im not sure on how to call the method to have it constantly listen and react to the servers sockt? I tried make a thread just before the return in doInBackGround but then the application starts works for a couple of seconds the force closes due to lack of memory? Do I need a thread to keep constantly listen?
The whole point of this as you might guess is to make a chat so the read method is eventually supposed to update a textView in my activity class. The send method is "working" but not as it should though this might be as I said earlier the server doing some funky buisness.
Another one, is it even possible to have the read as a method like I have or does something have to react when the server sends data and then call the method?
Edit
I have now moved the read part, or atleast some of it to doInBackGround so its now
dis = new BufferedReader(new InputStreamReader(socket.getInputStream()));
message = dis.readLine();
Log.i("AsynkTask", "Read : "+message+" this is doInBackGround!");
This along with a change to simply hardcode a printline in the server made me read that line in the client so im guessing its working realtively good for now.
How is it looking? Is it utter crap this code and should be done some other way? Got my functionality but never bad to learn to do it better so to speak :).
You should do both your writing and reading to the Socket in an AsyncTask's doInBackground() method, as both take time and could block the main (UI) thread. I don't know how you are calling your write() method above but you might also want to take a look at this question that might be related.

How to detect EOF on android bluetooth file transfer?

I have implemented a bluetooth connection using the now-classic Google Bluetooth Chat code. However, I have a question which I just cannot seem to wrap my brain around.
The reading of the input stream goes something like this:
public void run() {
byte[] buffer = new byte[1024]; // buffer store for the stream
int bytes; // bytes returned from read()
// Keep listening to the InputStream until an exception occurs
while (true) {
try {
// Read from the InputStream
bytes = mmInStream.read(buffer);
// Send the obtained bytes to the UI Activity
mHandler.obtainMessage(MESSAGE_READ, bytes, -1, buffer)
.sendToTarget();
} catch (IOException e) {
break;
}
}
}
Now, that's fine if I was just printing out the characters I was receiving as in the original example. However, suppose I wanted to transfer an image file. I don't know the size of the file, so I cannot count the bytes received or anything like that. In my tests, I don't seem to be ever receiving a "-1" from the input stream, which appears to be the "norm" for reading from input streams. So how can I know that I have reached the end of the file that was being sent?
Thank you for your help and your time.
It seems Android bluetooth input streams never return -1.
I guess setup a simple protocol by sending file size in the first place and EOF signals at last will help.
No it does not. Android sends -1 only when the Socket is closed as far as I know. So a workaround could be to do a reconnect, but I was trying that for hours and did not get it working, since I do not understand this "special" Code here (copied from a Stackoverflow Thread) for setting up the socket:
BluetoothSocket tmp = null;
Log.d(TAG, "New Connection initialized");
Method m;
try {
m = device.getClass().getMethod("createRfcommSocket",
new Class[] { int.class });
tmp = (BluetoothSocket) m.invoke(device, 1);
} catch (Exception e) {
e.printStackTrace();
}
mmSocket = tmp;
This Socket only works, when my App is started for the first filetransfer. If I want to "Reconnect" with a completely new instantiated Object (and a new Socket created with that Code), the program freezes on the blocking method mmSocket.connect(). It seems like the Method never comes to an ending. This is driving me nuts...
Try
while ((bytes = mmInStream.read(buffer) != -1)
and see if that helps.
Try this:
public void run() {
byte[] buffer;
ArrayList<Integer> arr_byte = new ArrayList<Integer>();
while (true) {
try {
int data = mmInStream.read();
if(mmInStream.available()>0) {
arr_byte.add(data);
} else {
arr_byte.add(data);
buffer = new byte[arr_byte.size()];
for(int i = 0 ; i < arr_byte.size() ; i++) {
buffer[i] = arr_byte.get(i).byteValue();
}
Log.e("INPUT",new String(buffer));
mHandler.obtainMessage(MESSAGE_READ, bytes, -1, buffer)
.sendToTarget();
arr_byte = new ArrayList<Integer>();
}
} catch (IOException e) {
break;
}
}
}

Categories

Resources