AsynkThread but still NetworkOnMainThreadException - android

I try to build up a connection between my android device and an arduino nano.
I tested the TCP connection between an raspberry pi zero and my arduino and it works and does what it is supposed to do.
Now i try to write the android app, but it throws the
android.io.NetworkOnMainThreadException
I found some hints to do it with AsynkTask but it still throws this exception. I found some solutions but neither did help in my case (eg: setting minAPI to 11).
public class MainActivity extends AppCompatActivity {
[...]
#Override
protected void onCreate(Bundle savedInstanceState) {
[...]
bt1.setOnClickListener(new View.OnClickListener(){
public void onClick(View v) {
onBtnClick();
}
}
}
public void onBtnClick() {
new Client().execute("0101010101");
}
private class Client extends AsyncTask<String, Void, String> {
protected String doInBackground(String[] params) {
// do above Server call here
return "null";
}
protected void onPostExecute(String msg) {
String reply ="";
try {
reply=sendData();
} catch(IOException e) {
e.printStackTrace();
reply = "IOException: "+e;
}
txt1.setText(reply);
}
public String sendData() throws IOException{
try {
// send message to Arduino
InetAddress serverAddr = InetAddress.getByName(ipAddress);
DatagramSocket clientSocket = new DatagramSocket();
send_data = str.getBytes();
DatagramPacket sendPacket = new DatagramPacket(send_data, send_data.length, serverAddr, portNumber);
clientSocket.send(sendPacket);
// get reply
byte[] receiveData1 = new byte[512];
DatagramPacket receivePacket = new DatagramPacket(receiveData1, receiveData1.length);
clientSocket.receive(receivePacket);
String reply = new String(receiveData1);
clientSocket.close();
return reply;
} catch (Exception e) {
e.printStackTrace();
return("Exception: "+ e);
}
}
}
}
What am i doing wrong? Thank you for your help.

The methods onPreExecute and onPostExecute runs on main thread, so, the method sendData should be executed on doInBackground
private class Client extends AsyncTask<String, Void, String> {
protected String doInBackground(String[] params) {
String reply ="";
try {
reply=sendData();
} catch(IOException e) {
e.printStackTrace();
reply = "IOException: "+e;
}
}
protected void onPostExecute(String msg) {
txt1.setText(reply);
}
public String sendData() throws IOException{
try {
// send message to Arduino
InetAddress serverAddr = InetAddress.getByName(ipAddress);
DatagramSocket clientSocket = new DatagramSocket();
send_data = str.getBytes();
DatagramPacket sendPacket = new DatagramPacket(send_data, send_data.length, serverAddr, portNumber);
clientSocket.send(sendPacket);
// get reply
byte[] receiveData1 = new byte[512];
DatagramPacket receivePacket = new DatagramPacket(receiveData1, receiveData1.length);
clientSocket.receive(receivePacket);
String reply = new String(receiveData1);
clientSocket.close();
return reply;
} catch (Exception e) {
e.printStackTrace();
return("Exception: "+ e);
}
}
}

Related

Android 6.0 cant create socket

I cant create a simple TCP connection to my server.
I created a AsyncTask to send messages, but it didn't work.
I added INTERNET and ACCESS_NETWORK_STATE to the permissions.
I don't know what else to try.
public class ServerCommunicator extends AsyncTask<String,Void,Void>{
public static String SERVER_IP = "192.168.2.148";
public static int SERVER_PORT = 1337;
public static String SERVER_PW = "adsfadsf";
public Context context;
#Override
protected Void doInBackground(String... params) {
//Create Command
CommandFactory cmdFactory = new CommandFactory();
Command cmd = cmdFactory.createCommand();
System.out.println("Cmd created..");
//-----
try {
System.out.println(SERVER_IP);
InetAddress serverAddr = InetAddress.getByName(SERVER_IP);
System.out.println("Created serverAddr "+ SERVER_IP);
Socket socket = new Socket(serverAddr,SERVER_PORT);
System.out.println("Socket created..");
//sends the message to the server
PrintWriter mBufferOut = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
String msg2Send = Crypter.Encrypt(cmd.toString(), SERVER_PW);
sendMsgAsByteArr(socket, msg2Send);
Command recCmd = cmdFactory.extractCommandFromStr(receiveMsg(socket));
socket.close();
Toast.makeText(context, recCmd.id, Toast.LENGTH_LONG).show();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
private static void sendMsgAsByteArr(Socket socket, String msg) {
try {
socket.getOutputStream().write(msg.getBytes());
System.out.println("sent cmd..");
} catch (IOException e) {
e.printStackTrace();
}
}
private static String receiveMsg(Socket socket) {
String msg = "";
int c;
ArrayList<Byte> incoming = new ArrayList<Byte>();
try {
while((c = socket.getInputStream().read())!=-1) {
incoming.add((byte)c);
}
byte[] allBytes = new byte[incoming.size()];
for(int i = 0; i < incoming.size(); i++) {
allBytes[i] = incoming.get(i);
}
msg = new String(allBytes);
} catch (IOException e) {
e.printStackTrace();
}
return msg;
}
}
My program runs till Socket socket = new Socket(serverAddr, SERVER_PORT); then it stops. It doesn't show any stack trace or errors.
Any ideas?
I debugged your code, and while there were multiple issues, none were related to Android 6.
I created a simplified version of your code and got it working.
One issue is that your context reference was null, so I set it in the constructor.
Another issue is that you were trying to show a Toast on a background thread, which won't work.
Another issue was your send and receive methods, they didn't work for me.
Here's the simplified code that I got working with a TCP/IP server, tested on both Android 4.4.4 and Android 6.
You can take this and expand on it as needed:
public class ServerCommunicator extends AsyncTask<String,Void,String> {
public static String SERVER_IP = "11.222.33.444";
public static int SERVER_PORT = 1234;
public Context context;
public ServerCommunicator(Context c) {
this.context = c;
}
#Override
protected String doInBackground(String... params) {
try {
System.out.println(SERVER_IP);
InetAddress serverAddr = InetAddress.getByName(SERVER_IP);
System.out.println("Created serverAddr "+ SERVER_IP);
Socket socket = new Socket(serverAddr,SERVER_PORT);
System.out.println("Socket created..");
//sends the message to the server
PrintWriter mBufferOut = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
String msg2Send = "{\"HelloWorld\", \"1234\"}";
mBufferOut.println(msg2Send);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String result = in.readLine();
System.out.println("result: " + result);
socket.close();
return result;
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String result) {
if (result != null) {
Toast.makeText(context, result, Toast.LENGTH_LONG).show();
}
}
}

Message not received from Python to Android with socket

my android application needs to communicate with a server python but at the time to receive a response, the answer does not come. These are my codes:
This is my Client:
public class MainActivity extends Activity {
private Socket socket;
private static final int SERVERPORT = 5589;
private static final String SERVER_IP = "192.168.1.131";
TextView risp;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
risp = (TextView) findViewById(R.id.textView1);
new Thread(new ClientThread()).start();
}
public void onClick(View view) {
try {
EditText et = (EditText) findViewById(R.id.editText1);
String str = et.getText().toString();
PrintWriter out = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream())), true);
out.println(str);
out.flush();
// Read from sock
BufferedReader input = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
StringBuilder response = new StringBuilder();
String line;
while ((line = input.readLine()) != null) {
response.append(line);
}
risp.setText(risp.getText().toString() + " " + response.toString());
out.close();
input.close();
socket.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
class ClientThread implements Runnable {
#Override
public void run() {
try {
InetAddress serverAddr = InetAddress.getByName(SERVER_IP);
socket = new Socket(serverAddr, SERVERPORT);
} catch (UnknownHostException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
And this is the Server:
import socket
import sys
# Create a TCP/IP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Bind the socket to the port
server_address = ('192.168.1.131', 5589)
print >>sys.stderr, 'starting up on %s port %s' % server_address
sock.bind(server_address)
# Listen for incoming connections
sock.listen(1)
while True:
# Wait for a connection
print >>sys.stderr, 'waiting for a connection'
connection, client_address = sock.accept()
try:
print >>sys.stderr, 'connection from', client_address
# Receive the data
while True:
data = connection.recv(1024)
if data.lower() != 'q':
print "<-- client: ", data
else:
print "Quit from Client"
connection.close()
break
data = raw_input("--> server: ")
if data.lower() != 'q':
connection.sendall(data)
else:
print "Quit from Server"
connection.close()
break
finally:
# Clean up the connection
print "Connection close"
connection.close()
The server receive the client message, but the client doesn't receive the server message. Why?
Thanks all in advance
EDIT: I SOLVED it this way:
public class MainActivity extends Activity {
private Socket socket;
private static final int SERVERPORT = 5589;
private static final String SERVER_IP = "192.168.1.131";
TextView risp;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
risp = (TextView) findViewById(R.id.textView1);
new Thread(new ClientThread()).start();
}
public void onClick(View view) {
new ConnectionTask().execute();
}
class ConnectionTask extends AsyncTask<String, Void, String> {
protected String doInBackground(String... params) {
String responce = null;
try {
EditText et = (EditText) findViewById(R.id.editText1);
String str = et.getText().toString();
PrintWriter out = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream())), true);
out.println(str);
out.flush();
InputStream input = socket.getInputStream();
int lockSeconds = 10*1000;
long lockThreadCheckpoint = System.currentTimeMillis();
int availableBytes = input.available();
while(availableBytes <=0 && (System.currentTimeMillis() < lockThreadCheckpoint + lockSeconds)){
try{Thread.sleep(10);}catch(InterruptedException ie){ie.printStackTrace();}
availableBytes = input.available();
}
byte[] buffer = new byte[availableBytes];
input.read(buffer, 0, availableBytes);
responce = new String(buffer);
out.close();
input.close();
socket.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return responce;
}
protected void onPostExecute(String responce) {
risp.setText(responce);
}
}
class ClientThread implements Runnable {
#Override
public void run() {
try {
InetAddress serverAddr = InetAddress.getByName(SERVER_IP);
socket = new Socket(serverAddr, SERVERPORT);
} catch (UnknownHostException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
}

How to stop Socket to send a lot of useless data when closed?

I use these codes for communicating between devices. If i close or kill the client app, the server app gets thousands of useless data. The textView in the server side is full of this: Client says: null. If i close the client twice, the server stops with StackOverFlowError. How can i make the code to dont send this null values when the app stops? Or can i filter the server side to do nothing when getting this data?
Client:
public class Client extends Activity {
private Socket socket;
private static final int SERVERPORT = 5000;
private static final String SERVER_IP = "10.0.2.2";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
new Thread(new ClientThread()).start();
}
public void onClick(View view) {
try {
EditText et = (EditText) findViewById(R.id.EditText01);
String str = et.getText().toString();
PrintWriter out = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream())),
true);
out.println(str);
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
class ClientThread implements Runnable {
#Override
public void run() {
try {
InetAddress serverAddr = InetAddress.getByName(SERVER_IP);
socket = new Socket(serverAddr, SERVERPORT);
} catch (UnknownHostException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
}
Server:
public class Server extends Activity {
private ServerSocket serverSocket;
Handler updateConversationHandler;
Thread serverThread = null;
private TextView text;
public static final int SERVERPORT = 1599;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
text = (TextView) findViewById(R.id.text2);
updateConversationHandler = new Handler();
this.serverThread = new Thread(new ServerThread());
this.serverThread.start();
}
#Override
protected void onStop() {
super.onStop();
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
class ServerThread implements Runnable {
public void run() {
Socket socket = null;
try {
serverSocket = new ServerSocket(SERVERPORT);
} catch (IOException e) {
e.printStackTrace();
}
while (!Thread.currentThread().isInterrupted()) {
try {
socket = serverSocket.accept();
CommunicationThread commThread = new CommunicationThread(socket);
new Thread(commThread).start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
class CommunicationThread implements Runnable {
private Socket clientSocket;
private BufferedReader input;
public CommunicationThread(Socket clientSocket) {
this.clientSocket = clientSocket;
try {
this.input = new BufferedReader(new InputStreamReader(this.clientSocket.getInputStream()));
} catch (IOException e) {
e.printStackTrace();
}
}
public void run() {
while (!Thread.currentThread().isInterrupted()) {
try {
String read = input.readLine();
updateConversationHandler.post(new updateUIThread(read));
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
class updateUIThread implements Runnable {
private String msg;
public updateUIThread(String str) {
this.msg = str;
}
#Override
public void run() {
text.setText(text.getText().toString()+"Client Says: "+ msg + "\n");
}
}
}
I think you should use a delimiter character, to tell the Server your Client it's about to die. Add that character of code in onPause method of your Android Activity/Fragment.
Then in your Server, just get the String or byte and compare it against your Delimiter String/Character and stop the Server listening for the Connection.
while (!Thread.currentThread().isInterrupted()) {
try {
String read = input.readLine();
updateConversationHandler.post(new updateUIThread(read));
} catch (IOException e) {
e.printStackTrace();
}
}
The problem is here. You aren't checking the result of readLine() for null. If it returns null, the peer has closed the connection and you should do likewise, and exit this loop. You can probably get rid of the isInterrupted() test as well.
Also, if you get any IOException other that a read timeout when reading from a socket, the connection is dead and you must close the socket and exit your loop.

how to update interface to MainActivity from thread activity in different class?

now i'm making socket connection to connect multiple client to one server. everything fine, i make thread in different class. But when i will fill textView with string from thread activity, i can't. please help
this MainActivity:
public class MainActivity extends Activity {
private static int port = 6000;
TextView txt;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
txt = (TextView) findViewById(R.id.txtCommand);
txt.setText("Server : ");
ServerSocket server1 = null;
Server gameServer = new Server();
try {
server1 = new ServerSocket(port);
// .. server setting should be done here
} catch (IOException e) {
System.out.println("Could not start server!");
// return ;
}
while (true) {
Socket client = null;
try {
client = server1.accept();
gameServer.handleConnection(client);
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class Server {
private ExecutorService executor = Executors.newCachedThreadPool();
public void handleConnection(Socket client) throws IOException {
PlayerConnection newPlayer = new PlayerConnection(this, client);
txt.setText(newPlayer.getuname());
this.executor.execute(newPlayer);
}
// add methods to handle requests from PlayerConnection
}
and this thread adctivity :
public class PlayerConnection implements Runnable {
private Server parent;
private Socket socket;
private PrintWriter out;
private BufferedReader in;
String line;
protected PlayerConnection(Server parent, Socket socket) throws IOException {
this.parent = parent;
this.socket = socket;
this.in = new BufferedReader(new InputStreamReader(socket
.getInputStream()));
this.out = new PrintWriter(new OutputStreamWriter(
socket.getOutputStream()));
}
public void run() {
while(!this.socket.isClosed()) {
try {
//int nextEvent = this.in.readInt();
line = in.readLine();
System.out.println("Server Receive : "
+ line);
out.println("Server Sent :" +line);
System.out.println("SEND : "
+ line);
out.flush();
if (line == null){
this.socket.isClosed();
break;
}
} catch (IOException e) {}
}
I realized that you have a while loop that never ends in your onCreate method. try to move that loop in to your thread. this loop blocks inputs of your application.
while (true) {
Socket client = null;
try {
client = server1.accept();
gameServer.handleConnection(client);
} catch (IOException e) {
e.printStackTrace();
}
you can use handler or runOnUiThread method.

Client & Server read and write on the same socket

I have an android client and a java server that use the same socket to send each other a string, but actually doesn't work and I don't know why.
Anyway, I need to use just one socket.
Here's the code for client and server:
public class CliActivity extends Activity implements OnClickListener {
Button b;
TextView tv;
BufferedReader in = null;
PrintStream out = null;
Socket client = null;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
b =(Button)findViewById(R.id.button1);
tv =(TextView)findViewById(R.id.textView1);
b.setOnClickListener(this);
}
public void onClick(View v) {
try {
client = new Socket("192.168.0.3",9000);
out = new PrintStream(client.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(client.getInputStream()));
out.write(("How are you?").getBytes());
out.close();
String message = in.readLine();
tv.setText(message);
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Server:
public class server {
public static void main(String[] args) {
BufferedReader in = null;
PrintStream out = null;
Socket client = null;
try {
ServerSocket server = new ServerSocket(9000);
client = server.accept();
out = new PrintStream(client.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(client.getInputStream()));
String message = in.readLine();
System.out.println(message);
out.write(("fine thanx").getBytes());
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Any suggestion?

Categories

Resources