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

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.

Related

Android TCP Socket InputStrem Intermittent Read or too Slow

I need to implement a TCP comunication between an IoT device(custom) and an Android App.
For the Wifi device we have a Server Socket, while in Android i have an AsyncTask as a Client Socket. Both the device and the smarthone are connected to the same network.
Here is the Android Client Socket code for the initialization/socket-read and socket-write:
Variables:
static public Socket nsocket; //Network Socket
static public DataInputStream nis; //Network Input Stream
static private OutputStream nos; //Network Output Stream
AsyncTask method doInBackgroud:
#Override
protected Boolean doInBackground(Void... params) { //This runs on a different thread
boolean result = false;
try {
//Init/Create Socket
SocketInit(IP, PORT);
// Socket Manager
SocketUpdate();
} catch (IOException e) {
e.printStackTrace();
Log.i("AsyncTask", "doInBackground: IOException");
clearCmdInStack();
MainActivity.SocketDisconnectAndNetworkTaskRestart();
result = true;
} catch (Exception e) {
e.printStackTrace();
Log.i("AsyncTask", "doInBackground: Exception");
result = true;
} finally {
try {
SocketDisconnect();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
Log.i("AsyncTask", "doInBackground: Finished");
}
return result;
}
Socket Initializzation:
public void SocketInit(String ip, int port) throws IOException {
InetAddress addr = InetAddress.getByName(ip);
SocketAddress sockaddr = new InetSocketAddress(addr, port);
nsocket = new Socket();
nsocket.setReuseAddress(false);
nsocket.setTcpNoDelay(true);
nsocket.setKeepAlive(true);
nsocket.setSoTimeout(0);
nsocket.connect(sockaddr, 0);
StartInputStream();
StartOutputStream();
}
Read from Socket:
private void SocketUpdate() throws IOException, ClassNotFoundException {
int read = 0;
// If connected Start read
if (socketSingleton.isSocketConnected()) {
// Print "Connected!" to UI
setPublishType(Publish.CONNECTED);
publishProgress();
if(mConnectingProgressDialog != null)
mConnectingProgressDialog.dismiss(); //End Connecting Progress Dialog Bar
//Set Communications Up
setCommunicationsUp(true);
Log.i("AsyncTask", "doInBackground: Socket created, streams assigned");
Log.i("AsyncTask", "doInBackground: Waiting for inital data...");
byte[] buffer = new byte[3];
do{
nis.readFully(buffer, 0, 3);
setPublishType(Publish.READ);
publishProgress(buffer);
}while(!isCancelled());
SocketDisconnect();
}
}
Streams init:
public void StartInputStream() throws IOException{
nis = new DataInputStream(nsocket.getInputStream());
}
public void StartOutputStream() throws IOException{
nos = nsocket.getOutputStream();
}
Read and Write methods:
public int Read(byte[] b, int off, int len) throws IOException{
return nis.read(b, off, len); //This is blocking
}
public void Write(byte b[]) throws IOException {
nos.write(b);
nos.flush();
}
public boolean sendDataToNetwork(final String cmd)
{
if (isSocketConnected())
{
Log.i("AsyncTask", "SendDataToNetwork: Writing message to socket");
new Thread(new Runnable()
{
public void run()
{
try
{
Write(cmd.getBytes());
}
catch (Exception e)
{
e.printStackTrace();
Log.i("AsyncTask", "SendDataToNetwork: Message send failed. Caught an exception");
}
}
}).start();
return true;
}
Log.i("AsyncTask", "SendDataToNetwork: Cannot send message. Socket is closed");
return false;
}
The application is very simple, the android app sends a command(via sendDataToNetwork method) to the IoT device and the latter sends back an "ACK" Command string.
The problem
The problem is that while the IoT device always receives the command, the smartphone rarely gets the ACK back. Sometimes i get something like "ACKACKACKACK". By debugging the IoT device i'm sure that it successfully sends back the ACK, so the problem lies in the InputStream read() method which doesn't retrieve the string right away.
Is there a way to empty the InputStream buffer right away, so that i get an "ACK" string back from the IoT device every time i send a command?
Update
I've updated the socket config so that there are no more buffer limitations and i've replaced read() method with readFully. It greatly improved, but still make some mistakes. For istance one out of 2-3 times no ack is received and i get 2 ack the next turn. Is this perhaps the computational limit of the IoT device? Or is there still margin for a better approach?
the problem lies in the InputStream read() method which doesn't empty the buffer right away.
I don't know what 'empty the buffer' means here, but InputStream.read() is specified to return as soon as even one byte has been transferred.
Is there a way to empty the InputStream buffer right away, so that i get an "ACK" string back from the IoT device every time i send a command?
The actual problem is that you could be reading more than one ACK at a time. And there are others.
If you're trying to read exactly three bytes, you should be using DataInputStream.readFully() with a byte array of three bytes.
This will also get rid of the need for the following array copy.
You should not mess with the socket buffer sizes except to increase them. 20 and 700 are both ridiculously small values, and will not be the actual values used, as the platform can adjust the value supplied. Your claim that this improved things isn't credible.
You should not spin-loop while available() is zero. This is literally a waste of time. Your comment says you are blocked in the following read call. You aren't, although you should be. You are spinning here. Remove this.

How to get result on running thread from many activity on android?

i have already get result from thread that running in same activity, but after change activity i cant get that result. is there any way to get that result ?
here my Thread, i get the result from runOnUiThread
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
public ConnectedThread(BluetoothSocket socket) {
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
// Get the input and output streams, using temp objects because
// member streams are final
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) { }
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
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);
final String s = new String(buffer);
runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(getApplicationContext(), s.toString(),
Toast.LENGTH_SHORT).show();
txtcomand.setText(s);
intent.putExtra("ct", s);
}
});
// Send the obtained bytes to the UI activity
// .obtainMessage(MESSAGE_READ, bytes, -1, buffer)
// .sendToTarget();
} catch (IOException e) {
break;
}
}
}
/* Call this from the main activity to send data to the remote device */
public void write(byte[] bytes) {
try {
mmOutStream.write(bytes);
} catch (IOException e) { }
}
/* Call this from the main activity to shutdown the connection */
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) { }
}
}
You could define an interface to communicate between different activitys or classes.
Just create the interface with methods that allow you to pass the data you need.
Then implement it on the receiver activity, when you create your second activity you need to pass the instance of the receiver activity and store it.
Then you can call that method and pass any parameter when you need.
Hope this helps.
I would recommend implementing a Service class instead of using a thread for your socket communication. A Service can run independently of your activities and different activities can communicate with your service in a number of ways.
For example i would implement a service and an event bus such as Otto (http://square.github.io/otto/) - its a few lines of code implementation. And then you can send your result without worrying about activities, and you activities/fragments can subscribe to those events. Its the easiest/safest way to communicate in your case, IMO, and you will have a nicely modular system.
Btw if you still want to use your thread, you can just add the event bus and use it for communication.
There are also other ways to pass that data. Interfaces for example, Broadcast receivers...

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

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.

Android application is freezed - Socket Exception

I made android application that connects to remote server and send some data.
Remote server is Windows application.
Connection method:
private void ConnectToMonitor() {
try {
s = new Socket(SERVER_ADDRESS, TCP_SERVER_PORT);
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
s.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
This works perfectly if server is online. Application is sending data and server is receiving. But if server is offline android app. is blocked. My question is how to handle this? How to continue with application and avoid error even the server is down?
Remember to call this outside the UIThread.
Follow this tutorial. In android all connections need to be managed outside the UIThread, in the tutorial I linked you will find easy ways to post your results back to the UI (handlers, asynctasks...)
Of course we don't know if the problem is about the thread with just the given code, but it is the most usual error.
First remember to set the socket timeout :
mSocket.setSoTimeout(timeout); //in milliseconds
You can however specify different timeout for connection and for all other I/O operations through the socket:
private void connectToMonitor() {
try {
socket = new Socket();
InetAddress[] iNetAddress = InetAddress.getAllByName(SERVER_ADDRESS);
SocketAddress address = new InetSocketAddress(iNetAddress[0], TCP_SERVER_PORT);
socket.setSoTimeout(10000); //timeout for all other I/O operations, 10s for example
socket.connect(address, 20000); //timeout for attempting connection, 20 s
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Second, in Android, you should perform any network I/O in separate threads!
As an example, using regular Java Threads :
String threadName = getClass().getName() + "::connect";
new Thread(new Runnable() {
#Override
public void run() {
connectToMonitor();
}
}, threadName).start();
You can set A timeout for the socket. Use Socket.setSoTimeout method
socket.setSoTimeout(timesinmilis);
by using this your socket will throw a socket timout exception. You can catch that and do what you want

Writing data to Android Bluetooth output stream throws: IllegalMonitorStateException

I have an Android Bluetooth application which manages a couple of remote devices(Capsules).
Writing data to the socket output stream of a Capsule worked yesterday, and after medium scale refactoring to the Android application only, I get the following error:
java.lang.IllegalMonitorStateException: attempt to unlock read lock, not locked by current thread.
Here is the socket creation code:
public final void connectWithCapsule(Capsule capsule)
throws Exception {
BluetoothSocket socket = capsulesSockets.get(capsule);
if (socket == null) {
try {
// Method m = capsule.getBT_Device().getClass().getMethod("createRfcommSocket", new Class[]{int.class});
// socket = (BluetoothSocket) m.invoke(capsule.getBT_Device(), Integer.valueOf(17));
socket = capsule.getBT_Device().createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
} catch (Exception e) {
logError("Error creating RFcomm socket", e);
throw e;
}
capsulesSockets.put(capsule, socket);
}
try {
socket.connect();
} catch (IOException e) {
logError("Error connecting socket", e);
try {
socket.close();
} catch (IOException e1) {
logError("Error closing socket", e1);
}
capsulesSockets.remove(capsule);
throw e;
}
}
and the model which manages the in/out streams:
public final class KitBT_ConnectionModel {
private final OutputStream[] outputStreams;
private final InputStream[] inputStreams;
public KitBT_ConnectionModel(OutputStream[] outputStreams, InputStream[] inputStreams) {
super();
this.outputStreams = outputStreams;
this.inputStreams = inputStreams;
}
public void transmitData(byte[] bs)
throws IOException {
for (OutputStream outputStream : outputStreams) {
outputStream.write(bs); // THIS LINE THROWS THE EXCEPTION
outputStream.flush();
}
}
public InputStream[] getInputStreams() {
return inputStreams;
}
}
Note: I do not perform any action with both of the streams, and the first write causes the exception.
First thing that pops to mind is which thread puts the read lock and when?
I've tried to play around with the threads which call the socket creation, and the streams transactions, I've made sure, 100% sure they have both been accessed by the same thread (and also tried accessing with different threads), but this exception persists.
Please enlighten me...
HAAAAAAAAAAAAAAAAAAa.........
Darn this LG phones!!!!
I gave the phone a hard reboot, removed the battery and started it over, and it works again...
turning the Bluetooth off and on didn't do the trick! I've been doing it for the past day or so.
God damn it nearly 24 hours of waste for nothing....
How messed up can these products be!
at least it works now!

Categories

Resources