I'm using a TimerTask to get the result of a Wi-Fi scan on a specific interval. I want to send the scanning results to a server.So I used AsyncTask to send the results. When I call the AsyncTask from inside the TimerTask my application crashes. Can anyone tell me why this is happening? Also in my code what is the best way to send the result to a server?
Here is my code:
public class ServerComm extends AsyncTask<String, Void, String>{
int port=9999;
String IP="192.168.2.100";
BufferedReader input;
#Override
protected String doInBackground(String... scanRes) {
// TODO Auto-generated method stub
Socket socket;
String loc="";
FileWriter writer;
File sock=new File(Environment.getExternalStorageDirectory()+"/network.txt");
try {
writer = new FileWriter(sock, true);
writer.append("in async task.\n");
writer.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
InetAddress serverAddr = InetAddress.getByName(IP);
socket = new Socket(serverAddr, port);// socket is created
input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
Log.d("ser","socket");
// now send
PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())),true);
out.println(scanRes);
// get the reply
loc = input.readLine();
//close
socket.close();
return loc;
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return loc;
}
#Override
protected void onPostExecute(String result) {
// draw the new location on the map
}
This is the code of the TimerTask:
public void Locate()
{
if(isScanning)// if a previous scan is running cancel it
{
timer.cancel();
}
else
{
timer.schedule(new TimerTask() { // start new scanner
#Override
public void run() {
// TODO Auto-generated method stub
if(counter==numOfScans)
{
try {
writer = new FileWriter(file, true);
writer.append(RSS+" \n");
writer.append("Finished Collecting RSSIs.\n");
writer.close();
new ServerComm().execute(RSS);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
timer.cancel();
}
else // not finished
{
isScanning=true;
if(result!=null)
{
if(result.size()!=0)
{
for(int i=0;i< result.size();i++)
{
RSS=RSS+result.get(i).BSSID+" "+result.get(i).level+" ";
}//end for
counter++;
} // end of if
}//end of else
}
}
}, 0,Interval);
}
//get location
}
I solved the problem, so I'm posting the answer in case someone else faced the same problem.
The problem was the AsyncTask should not be called from TimerTask. A handler should be used to run the AsyncTask Like this:
Handler h = new Handler(Looper.getMainLooper());
h.post(new Runnable() {
public void run() {
new ServerComm().execute(RSS);
}
});
This is solution is by arthvading on this question.
Related
I'm having a weird problem. I'm creating a socket and giving it the IP 192.168.43.255. When I use InetAddress.getByName(IP) it adds / to the ip as shown in the log below. Why this is happening ??
here is my code
public class ServerCom extends AsyncTask<String, Void , String>{
private int port=9999;
private String IP="192.168.43.255";
private BufferedReader input;
private Socket socket;
private DataOutputStream toSer;
private InetAddress serverAddr;
private String LocationID;
File file;FileWriter writer;
#Override
protected String doInBackground(String... RSS) {
// TODO Auto-generated method stub
Log.d("s","async");
SandboxView.Locate=false;
try {
serverAddr = InetAddress.getByName(IP);
socket = new Socket(serverAddr, port);
toSer = new DataOutputStream(socket.getOutputStream());
input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
} catch (UnknownHostException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// send result to server
try {
toSer.writeBytes(RSS[0]+"\n");
//get the response from server
LocationID=input.readLine();
toSer.close();
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return LocationID;
}
protected void onPostExecute(String result)
{
super.onPostExecute(result);
//dismiss progressdialog.
//update ui
MainActivity.LocationID=LocationID;
SandboxView.Localization=MainActivity.CH2.getLocation(LocationID);
try {
writer = new FileWriter(file, true);
writer.append("room :"+LocationID+"\n");
writer.append(SandboxView.Localization.x+" "+SandboxView.Localization.y+"\n");
writer.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
MainActivity.view.invalidate();
SandboxView.Locate=true;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
}
05-16 17:53:16.331: W/System.err(3495): java.net.ConnectException: /192.168.43.255:9999 - Network is unreachable
This isn't really adding a / to the IP address, but the format of the address output by InetAddress.toString() uses a / to separate the hostname from the host address. See here. So, the / isn't really being added to the address, it is just shown in the logging.
I am sending image using Socket Server and Client. It gived me dialog "App not responding" i think beacuse converting this bitmap was making in UiThread. So i tried to change it but i am still getting this message "App is not responding". It's happening when i am sending big imaes +500kb.
Here is my code for Server:
public class SocketServerThread extends Thread {
static final int SocketServerPORT = 8080;
int count = 0;
#Override
public void run() {
try {
serverSocket = new ServerSocket(SocketServerPORT);
while (true) {
Socket socket = serverSocket.accept();
count++;
// Here where i am doing my code i think is not doing in UiThread..
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run()
{
// Firstly i was doing my code here...
}
});
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
My code for client:
public class MyClientTask extends AsyncTask<Void, Void, Void> {
MyClientTask(String addr, int port){
dstAddress = addr;
dstPort = port;
}
#Override
protected Void doInBackground(Void... arg0) {
Socket socket = null;
try
{
//I am sending my image here...
}
}
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
response = "UnknownHostException: " + e.toString();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
response = "IOException: " + e.toString();
}finally{
if(socket != null){
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return null;
}
#Override
protected void onPostExecute(Void result)
{
super.onPostExecute(result);
}
}
So please help my . Why still i am getting not responding dialog?
The ANR error code happens when you block the UI thread more than 5 seconds. If you need to do background work don't use the main thread. Receive the data in a separate thread and post only the result to the UI thread.
I googled it and StackoverFlow but there's not much information I can use.
And most of the answers suggest to use thread, don't open socket in main thread.
Anyway my code like this
public class Client implements Runnable {
private Socket socket;
private static ObjectOutputStream oos;
public Client() {
mPauseLock = new Object();
mPaused = false;
mFinished = false;
try {
socket = new Socket("168.131.148.50", 5001);
pw = new PrintWriter(socket.getOutputStream(), true);
oos = new ObjectOutputStream(socket.getOutputStream());
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void run() {
for (int i = 0; i < MsgQueue.getSize(); i++) {
try {
oos.writeObject(MsgQueue.get(i));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
and in MainActivity
new Thread(new Client()).start();
But still I get NetworkOnMainThreadExcpetion..
Can anybody tell me solution please?
try moving the initialization code in the constructor right before the for loop in run()
You are doing the socket call in the main thread when calling the line "new Client()", you should move all the code related to the socket creation inside the run method, you must know that only the "run" method is executed in the background thread, not the class initialization:
public class Client implements Runnable {
private Socket socket;
private static ObjectOutputStream oos;
public Client() {
mPauseLock = new Object();
mPaused = false;
mFinished = false;
}
public void run() {
try {
socket = new Socket("168.131.148.50", 5001);
pw = new PrintWriter(socket.getOutputStream(), true);
oos = new ObjectOutputStream(socket.getOutputStream());
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
for (int i = 0; i < MsgQueue.getSize(); i++) {
try {
oos.writeObject(MsgQueue.get(i));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
You should read more about java before jumping into Android...
Regards!
I am using FTP to upload a file. This works great. This file contains information what the app should do.
So I am doing the following:
1) Download the file with Apache FTP Client (seems to work fine)
2) Try to read out the file with a BufferedReader and FileReader.
The problem:
I get a NullPointerException while reading the file. I guess that this is a timing problem.
The code has this structure:
...
getFile().execute();
BufferedReader br = new BufferedReader(...);
How can I solve this problem?
I have to use a seperate Thread (AsyncTask) to download the file because otherwise it will throw a NetworkOnMainThread Exception.
But how can I wait until the file is completely downloaded without freezing the UI?
I cannot use the BufferedReader inside AsyncTask because I use GUI elements and I have to run the interactions on the GUI Thread, but I have no access to it from AsyncTask. RunOnUiThread does not work as well because I am inside a BroadcastReceiver.
Some code:
private class GetTask extends AsyncTask{
public GetTask(){
}
#Override
protected Object doInBackground(Object... arg0) {
FTPClient client = new FTPClient();
try {
client.connect("*****");
}
catch (SocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
client.login("*****", "*****");
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
FileOutputStream fos = null;
try {
fos = new FileOutputStream( "/sdcard/"+userID+".task" );
}
catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
resultOk &= client.retrieveFile( userID+".task", fos );
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
Thread.sleep(5000);
}
catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}/**
try {
client.deleteFile(userID+".task");
}
catch (IOException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
}
**/
try {
client.disconnect();
}
catch (IOException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
}
return null;
}
}
The Broadcastreceiver class:
public class LiveAction extends BroadcastReceiver {
...
private Context cont;
FileReader fr = null;
BufferedReader br;
#Override
public void onReceive(Context context, Intent intent)
{
cont = context;
...
new GetTask().execute();
try {
Thread.sleep(3000);
}
catch (InterruptedException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
}
try {
fr = new FileReader("/sdcard/"+userID+".task");
}
catch (FileNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
br = new BufferedReader(fr)
String strline = "";
try {
while ((strline = br.readLine()) != null){
if(strline.equals("taskone")){
//Some GUI Tasks
}
....
This is the relevant code.
I think the best approach would be to read the file's contents from the doInBackground inside the AsyncTask and then output an object which contains the info you need on the onPostExecute method of the async stask and then manipulate your UI.
private AsyncTask<String,Void,FileInfo> getFile(){
return new AsyncTask<String,Void,FileInfo>{
protected FileInfo doInBackground(String url){
FileInfo finfo = new FileInfo(); // FileInfo is a custom object that you need to define that has all the stuff that you need from the file you just downloaded
// Fill the custom file info object with the stuff you need from the file
return finfo;
}
protected void onPostExecute(FileInfo finfo) {
// Manipulate UI with contents of file info
}
};
}
getFile().execute();
Another option is to call another AsyncTask from onPostExecute that does the file parsing but I would not recommend it
I would try some thing like this:
private class GetTask extends AsyncTask{
LiveAction liveAction;
public GetTask(LiveAction liveAction){
this.liveAction = liveAction;
}
...
#Override
protected void onPostExecute(String result) {
liveAction.heyImDoneWithdownloading();
}
}
Ps: why the Thread.sleep(5000)?
public class LiveAction extends BroadcastReceiver {
...
public void heyImDoneWithdownloading(){
//all the things you want to do on the ui thread
}
}
i've done an application in which the android application send datas to java desktop swing application as well as send datas from desktop to android using TCP socket programming through wifi.
Th application is a Hotel Kitchen order booking system
The problem describes that Dine_Tables class contains buttons which represents each tables in a hotel, on clicking table1 button for example it starts the BackgroundServers Asyntask which runs a server for receiving desktop application datas also it takes the activity from Dinein_Tables.java to Food_Customizer.java.
In Food_Customizer.java on clicking submit button it starts ServersendAsyncAction Asyntask which sends some datas to desktop swing application.
The desktop application after processing sends some datas to android application, The server that runs in the android application on receiving the datas goes again from Food_Customizer.java to Dinein_Tables.java activity in the BackgroundServers Asyntask onPostExecute method.
The problem is that when i do this process a two or three times the application stop due to address-in use and Null-Pointer exception at socket = serverSocket.accept(); in the BackgroundServers Asyntask.
Can anyone please tell me some solution for this problem
Dinein_Tables.java
public class Dinein_Tables extends Activity {
:
:
table1.setOnClickListener(new OnClickListener() {
public void onClick(final View v) {
new Handler().postDelayed(new Runnable() {
public void run() {
Food_Customizer.BackgroundServers ob = new Food_Customizer().new BackgroundServers(contexts);
ob.execute("");
Intent toAnotherActivity = new Intent(v.getContext(), Food_Customizer.class);
startActivity(toAnotherActivity);
finish();
}
}, 100L);
}
});
}
Food_Customizer.java
public class Food_Customizer extends Activity {
:
:
submit= (Button)findViewById(R.id.submit);
submit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
pd = ProgressDialog.show(contexts, "Sending to Server...","Please Wait...", true, false);
new ServersendAsyncAction().execute();
}
});
:
:
/****************************** AsyncTask ********************************************************/
private class ServersendAsyncAction extends AsyncTask<String, Void, String> {
/****************************** AsyncTask doInBackground() ACTION ********************************/
protected String doInBackground(String... args) {
Socket socket = null;
DataOutputStream dataOutputStream = null;
DataInputStream dataInputStream = null;
boolean flag = true;
while (flag) /******** If data is send flag turn to be false *******/
{
try {
socket = new Socket("192.168.1.74", 4444);
dataOutputStream = new DataOutputStream(socket.getOutputStream());
dataInputStream = new DataInputStream(socket.getInputStream());
dataOutputStream.writeUTF(datastosend);
flag = false;
} catch (UnknownHostException e) {
flag = true;
e.printStackTrace();
} catch (IOException e) {
flag = true;
e.printStackTrace();
}
/******** CLOSING SOCKET *****************/
finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/******** CLOSING DATAOUTPUTSTREAM *******/
if (dataOutputStream != null) {
try {
dataOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/******** CLOSING DATAINPUTSTREAM ********/
if (dataInputStream != null) {
try {
dataInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
return null;
/******** returns what you want to pass to the onPostExecute() *******/
}
/****************************** AsyncTask onPostExecute() ACTION *********************************/
protected void onPostExecute(String result) {
}
/********************* ENDING OF ASYN TASK CLASS ServersendAsyncAction ***************************/
}
public Context con;
public static ServerSocket serverSocket = null;
public class BackgroundServers extends AsyncTask<String, Void, String> {
public BackgroundServers(Context context) {
con=context;
}
/****************************** AsyncTask doInBackground() ACTION ********************************/
protected String doInBackground(String... args) {
Socket socket = null;
DataInputStream dataInputStream = null;
DataOutputStream dataOutputStream = null;
try {
serverSocket = new ServerSocket(9999);
System.out.println("Listening :9999");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
while (true) {
try {
socket = serverSocket.accept();
dataInputStream = new DataInputStream(
socket.getInputStream());
dataOutputStream = new DataOutputStream(socket.getOutputStream());
System.out.println("ip: " + socket.getInetAddress());
String incoming_message=(dataInputStream.readUTF());
incoming_message=incoming_message.replace("/", "");
String recdatas[]=incoming_message.split("#");
if(recdatas[0].equalsIgnoreCase("success"))
{
DatabaseConnection dbs=new DatabaseConnection(con);
int status=dbs.update("UPDATE hotel_pub_tables SET status='occupied' WHERE tableno='"+recdatas[1]+"'");
if(status>0)
{
tabelstatus=1;
//msg.obj="Table status changed!!!";
System.out.println("Table status changed!!!");
if (true) {
System.out.println("entered 222");
System.out.println(tabelstatus);
if(tabelstatus==1)
{
System.out.println(tabelstatus);
Food_Customizer.pd.dismiss();
System.out.println("success");
}
else if(tabelstatus==2)
{
Food_Customizer.pd.dismiss();
Intent intent = new Intent(Food_Customizer.this, Dinein_Tables.class);
startActivity(intent);
finish();
}
}
}
else
tabelstatus=2;
dbs.close();
}
dataOutputStream.writeUTF("Hello!");
} catch (IOException e) {
e.printStackTrace();
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (dataInputStream != null) {
try {
dataInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (dataOutputStream != null) {
try {
dataOutputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return null;
}
/******** returns what you want to pass to the onPostExecute() *******/
}
/****************************** AsyncTask onPostExecute() ACTION *********************************/
#Override
protected void onPostExecute(String result) {
System.out.println("eneterd on posttttttttttttttt");
con.startActivity(new Intent(con, Dinein_Tables.class));
finish();
}
}
}
/********************* ENDING OF ASYN TASK CLASS BackgroundServers ***************************/
}
Well it's obvious that you setup your server on port 9999:
serverSocket = new ServerSocket(9999);
But you connect with the server on port 4444:
socket = new Socket("192.168.1.74", 4444);
Make sure you connect to the correct port-number otherwise it wont work. Hope this helps.