Communicate with an AsyncTask in Android? - android

I'm running a socket client in my AsyncTask. I need to find a way to call send externally. Ex: socketClient.send(msg); SocketClient is defined in a service. Send will be called when the UI sends a broadcast and the service receives it. So far all my attempts have caused the app to crash.
Here is my code:
public class SocketClient extends AsyncTask<Void, Void, Void> {
private String ip;
private int port;
private Socket socket = null;
private BufferedReader in = null;
private PrintWriter out = null;
private boolean connected;
String devID;
public SocketClient(String ip, int port, String devID){
this.ip = ip;
this.port = port;
this.devID = devID;
connected = true;
}
#Override
protected Void doInBackground(Void... arg0){
try{
socket = new Socket(ip, port);
} catch(Exception ex){
socket = null;
}
try{
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
send(new SocketMessage("ident", "sdas", "", ""));
while(connected) {
SocketMessage msg = new SocketMessage(in.readLine());
handle(msg);
}
//clean up
out.println(new SocketMessage("quit", "","", ""));
out.flush();
} catch(Exception ex){
ex.printStackTrace();
}
finally{
try{
connected = false;
out.close();
in.close();
socket.close();
}catch(Exception ex){
ex.printStackTrace();
}
}
return null;
}
public void handle(SocketMessage msg){
}
public synchronized void send(SocketMessage msg){
out.println(msg.getJSON());
out.flush();
}
}

The AsyncTask is not designed for long running processes. In that case you are better of using a Thread. See the developer guide for Connecting Techniques.

Try an event bus like Otto from Square or Event Bus from Green Robot. IPC is difficult in Android and these libraries abstract it to make it less painful to work with.

Related

AsynkThread but still NetworkOnMainThreadException

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);
}
}
}

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();
}
}
}

Android client getting all the inputStreamReader at the deco from the server

I'm asking for a little help here..
I made a Android app in order to get messages from a server. The app just have to show the server's messages and nothing else.
the thing is nothing is shown in the UI, all the messages are shown when I disconnect the server.
It's frustrating because the app get the data's, just don't show them before the disconnection of the server.
Here is my code :
public class SlimpleTextClientActivity extends Activity {
private TextView textView;
private Socket client;
private PrintWriter printwriter;
private BufferedReader bufferedReader;
//Following is the IP address of the chat server. You can change this IP address according to your configuration.
// I have localhost IP address for Android emulator.
private String CHAT_SERVER_IP = "192.168.2.2";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_slimple_text_client);
textView = (TextView) findViewById(R.id.textView1);
ChatOperator chatOperator = new ChatOperator();
chatOperator.execute();
}
/**
* This AsyncTask create the connection with the server and initialize the
* chat senders and receivers.
*/
private class ChatOperator extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... arg0) {
try {
client = new Socket(CHAT_SERVER_IP, 6666); // Creating the server socket.
if (client != null) {
printwriter = new PrintWriter(client.getOutputStream(), true);
InputStreamReader inputStreamReader = new InputStreamReader(client.getInputStream());
bufferedReader = new BufferedReader(inputStreamReader);
} else {
System.out.println("Server has not bean started on port 4444.");
}
} catch (UnknownHostException e) {
System.out.println("Faild to connect server " + CHAT_SERVER_IP);
e.printStackTrace();
} catch (IOException e) {
System.out.println("Faild to connect server " + CHAT_SERVER_IP);
e.printStackTrace();
}
return null;
}
/**
* Following method is executed at the end of doInBackground method.
*/
#Override
protected void onPostExecute(Void result) {
Receiver receiver = new Receiver(); // Initialize chat receiver AsyncTask.
receiver.execute();
}
}
/**
* This AsyncTask continuously reads the input buffer and show the chat
* message if a message is availble.
*/
private class Receiver extends AsyncTask<Void, Void, Void> {
private String message;
#Override
protected Void doInBackground(Void... params) {
while (true) {
try {
if (bufferedReader.ready()) {
message = bufferedReader.readLine();
publishProgress(null);
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
#Override
protected void onProgressUpdate(Void... values) {
textView.append( message + "\n");
}
}
}
Hope that someone have an idea because here... I don't x)
Simon !
EDIT :
So... I went to java to test my code (simplification with the System.out.println)
Here is my code :
public class MainClass {
public static void main(String[] args) throws Exception {
final Socket client;
InputStream is = null;
InputStreamReader isr = null;
BufferedReader br = null;
try{
client = new Socket("192.168.2.2", 6666);
InputStreamReader inputStreamReader = new InputStreamReader(client.getInputStream());
// create new buffered reader
br = new BufferedReader(inputStreamReader);
int value=0;
String monChar = null;
String maChaine = null;
//System.out.println(maChaine);
// reads to the end of the stream
while((value = br.read()) != -1)
{
// converts int to character
char c = (char) value;
maChaine = maChaine + c;
}
}catch(Exception e){
e.printStackTrace();
}finally{
// releases resources associated with the streams
if(is!=null)
is.close();
if(isr!=null)
isr.close();
if(br!=null)
br.close();
}
}
}
The thing is that I can't reach maChaine.
This does the same thing that before : I only can reach my String when the server is disconected.
If I put a "System.out.println(maChaine);" in my While it will print something at each rows and if I put it after it will only do something if the server is disconected.

How to listen for incoming messages from sockets of threads to update a Listview in android?

I am developing an android application in which I have to create a multiple clients connection with one server. At the server side I am creating a new thread for every client and it is working fine, but in the new created thread where I am listening for a messages from socket and updating a list view created in a fragment, it is not getting updated. Please help me to solve this issue.
public class ClientSocketHandler extends Thread {
private static final String TAG = "ClientSocketHandler";
//private Handler handler;
// private ChatManager chat;
private InetAddress mAddress;
InputStream dataInputStream=null;
OutputStream dataOutputStream=null;
static String msgToSend="";
int i;
char c;
String newMsg="";
Boolean flag=true;
WiFiChatFragment frg;
Handler handler;
public ClientSocketHandler(InetAddress groupOwnerAddress) {
this.mAddress = groupOwnerAddress;
//this.handler=handl;
}
#Override
public void run() {
Socket socket = new Socket();
try {
socket.bind(null);
socket.connect(new InetSocketAddress(mAddress.getHostAddress(),
WiFiServiceDiscoveryActivity.SERVER_PORT), 5000);
Log.d(TAG, "Launching the I/O handler");
dataInputStream = socket.getInputStream();
dataOutputStream = socket.getOutputStream();
while (true) {
while(flag){
if((i=dataInputStream.read())!=1){
frg.pushMessage(newMsg);
newMsg="";
flag=false;
}
else{
c=(char)i;
newMsg+=c;}
}
if(!msgToSend.equals("")){
dataOutputStream.write(msgToSend.getBytes());
dataOutputStream.flush();
msgToSend = "";
}
}
} catch (IOException e) {
e.printStackTrace();
try {
socket.close();
} catch (IOException e1) {
e1.printStackTrace();
}
return;
}
}
public static void sendMsg(String msg){
msgToSend = msg;
}
}
I think this can happen of any of the following this is not handled.
1. Set the list adapted
2. Check that data is received on client and added to the data source.
3. Call the notifyDataSetChanged() after adding the data to data source for ListView.

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.

Categories

Resources