I'm new to android application development. I tried to develop an android server client chat
for my first project. This is the code for the client side. When the client press btnJoin
,
it will connect to the server and send a string. I've read many example and many of them
looks like this. I got a networkOnMainThreadException
. How do I make an asyncTask
to prevent
this problem? Any help would be much appreciated.
btnJoin = (Button) findViewById(R.id.buttonJoin);
btnJoin.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Socket socket = null;
DataOutputStream dataOutputStream = null;
DataInputStream dataInputStream = null;
try {
socket = new Socket("192.168.1.4", 9092);
dataOutputStream = new DataOutputStream(socket.getOutputStream());
dataInputStream = new DataInputStream(socket.getInputStream());
dataOutputStream.writeUTF("Hello server!");
txtIP.append(dataInputStream.readUTF() + "\n");
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (dataOutputStream != null) {
try {
dataOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (dataInputStream != null) {
try {
dataInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
});
Change your code as:
btnJoin.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view){
new LongOperation().execute("");
}
}
private class LongOperation extends AsyncTask<String, Void, String> {
Socket socket = null;
String strresult="";
DataOutputStream dataOutputStream = null;
DataInputStream dataInputStream = null;
@Override
protected String doInBackground(String... params) {
try {
socket = new Socket("192.168.1.4", 9092);
dataOutputStream = new DataOutputStream(socket.getOutputStream());
dataInputStream = new DataInputStream(socket.getInputStream());
dataOutputStream.writeUTF("Hello server!");
strresult.append(dataInputStream.readUTF() + "\n");
// txtIP.append(dataInputStream.readUTF() + "\n");
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (dataOutputStream != null) {
try {
dataOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (dataInputStream != null) {
try {
dataInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return strresult;
}
@Override
protected void onPostExecute(String result) {
TextView txtIP= (TextView) findViewById(R.id.txtIP);
// txtIP.append(result + "\n");
txtIP.setText(result + "\n");
}
@Override
protected void onPreExecute() {
}
}
Use AsyncTask like this :
First have it nested in your class, it should look similar to :
private class Communicator extends AsyncTask<Void, Void, Boolean> {
String tmp;
String err;
@Override
protected Boolean doInBackground() {
try {
socket = new Socket("192.168.1.4", 9092);
dataOutputStream = new DataOutputStream(socket.getOutputStream());
dataInputStream = new DataInputStream(socket.getInputStream());
dataOutputStream.writeUTF("Hello server!");
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (dataOutputStream != null) {
try {
dataOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (dataInputStream != null) {
try {
dataInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return true;
}
@Override
protected void onPreExecute() {
}
@Override
protected void onPostExecute(Boolean result) {
txtIP.append(dataInputStream.readUTF() + "\n");
}
}
When you have AsyncTask,you can start it like this :
...
@Override
public void onClick(View v) {
Communicator c=new Communicator();
c.execute();
}
....
try to implement this code in your app
private class LongOperation extends AsyncTask<Object, Integer, Object> {
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected Object doInBackground(Object... params) {
//do hard work here
return params;
}
@Override
protected void onProgressUpdate(Integer... values) {
}
@Override
protected void onPostExecute(Object result) {
super.onPostExecute(result);
}
}
AsyncTask must be subclassed to be used. The subclass will override at least one method (doInBackground(Params...)), and most often will override a second one (onPostExecute(Result).)
Here is an example of subclassing:
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
protected Long doInBackground(URL... urls) {
int count = urls.length;
long totalSize = 0;
for (int i = 0; i < count; i++) {
totalSize += Downloader.downloadFile(urls[i]);
publishProgress((int) ((i / (float) count) * 100));
// Escape early if cancel() is called
if (isCancelled()) break;
}
return totalSize;
}
protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]);
}
protected void onPostExecute(Long result) {
showDialog("Downloaded " + result + " bytes");
}
}
Once created, a task is executed very simply:
new DownloadFilesTask().execute(url1, url2, url3);
for more details refer below links...
http://www.vogella.com/articles/AndroidPerformance/article.html
http://developer.android.com/reference/android/os/AsyncTask.html