This question was asked and answered some time ago link. However the answer did not help me yet. I am in sort of the same position as the OP of the other post:
I have an Asynctask in which I make a connection to a certain website, however, most of the time the connection will take some time due to a laggy internetconnection.
I want the user to be able to stop trying to connect at any time.
public class DownloadWebHtml extends AsyncTask<String, Void, Map<String,ArrayList<ArrayList<String>>>> {
HttpURLConnection con = null;
#Override
protected void onPreExecute(){
Button but = (Button) findViewById(301);
but.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
cancel(true);
con.disconnect();
}
});
}
#Override
protected Map<String, ArrayList<ArrayList<String>>> doInBackground(String... urlcodes) {
//stuff
BufferedReader in = null;
try {
URL url = new URL("some url");
con = (HttpURLConnection) url.openConnection();
in = new BufferedReader(new InputStreamReader(con.getInputStream(),Charset.forName("ISO-8859-1")));
String line = "";
while ((line = in.readLine()) != null && !isCancelled()) {
html.add(line);
}
in.close();
} catch (MalformedURLException e) {
return null;
} catch (IOException e) {
return null;
} finally {
con.disconnect();
if (in != null) {
try {
in.close();
} catch (IOException e) {
Log.d("gettxt", e.getMessage());
}
}
}
if(!html.isEmpty()) {
return //stuff;
}
return null;
}
#Override
protected void onCancelled(){
//cancellation
}
//onpostexecute doing stuff
}
Whenever the button is pressed the whole AsyncTask will by cancelled only after a connection has been made.
Is it possible to immediately stop the whole process on a button press?
Can it be done using the default httpurlconnection?
I tried using the disconnect to trigger an exception while the con.getInputStream is busy, but it failed to work.
I recommend switching to Apache's HTTP Components. It works a charm, and has a thread-safe abort method, as outlined here.
Related
I am downloading JSON Content from server in the MainActivity and passing the JSON from MainActivity to ListActivity, the problem here is I have added a sleep time of 10s in the backend server i.e. Php from where the data is fetched. Since, the response will the delayed I would expect that screen opens and waits until the response comes and move to next screen.
But what is happening is the screen goes white/black completely untill the response is recieved and ListActivity is loaded, the problem here is the MainActivity is never visible. Below is code for the same:
MainActivity
JSONData jsonData = new JSONData();
String jsonList = jsonData.fetchList();
Intent intent = new Intent(getApplicationContext(),ListActivity.class);
intent.putExtra("jsonList",jsonList);
startActivity(intent);
finish();
JSON Data class
public String fetchList() {
try {
String list = new DownloadJSONData().execute(listURL).get().toString();
return list;
} catch (Exception e) {
return "";
}
}
private class DownloadJSONData extends AsyncTask<String, String, String> {
protected void onPreExecute() {
super.onPreExecute();
}
protected String doInBackground(String... params) {
HttpURLConnection connection = null;
BufferedReader reader = null;
try {
URL url = new URL(params[0]);
connection = (HttpURLConnection) url.openConnection();
connection.connect();
InputStream stream = connection.getInputStream();
reader = new BufferedReader(new InputStreamReader(stream));
StringBuffer buffer = new StringBuffer();
String line;
while ((line = reader.readLine()) != null) {
buffer.append(line + "\n");
}
return buffer.toString();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (connection != null) {
connection.disconnect();
}
try {
if (reader != null) {
reader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return "";
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
}
}
you are using get() method which accquires the main thread or ui thread untill the async task is completed
you should avoid using get() and also can use progress dialog in onPreExecute for displaying progression on network call to user
Is there any way to ping a url on Activity onDestroy event. I have tried to use AsyncTask as some tutorial said that it will execute after onDestroy but it doesn't work.
This is the class i ping on destroy
public class inactive extends AsyncTask<String, Integer, String> {
#Override
protected String doInBackground(String... params) {
String res = new String();
try {
BufferedReader reader = null;
URLConnection uc = null;
try {
URL urll = new URL(new StringBuilder()
.append("www.myuru.com").toString());
uc = urll.openConnection();
uc.connect();
reader = new BufferedReader(new InputStreamReader(uc.getInputStream()));
StringBuffer buffer = new StringBuffer();
int read;
char[] chars = new char[1024];
while ((read = reader.read(chars)) != -1)
buffer.append(chars, 0, read);
res = buffer.toString();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (reader != null) {
reader.close();
}
}
} catch (Exception e) {
e.printStackTrace();
}
return res;
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
}
}
and this is the onDestroy method from my activity
#Override
protected void onDestroy() {
new inactive(this, sharedpreferences).execute();
super.onDestroy();
}
My tests have shown that this code breaks when it tries to open the connection (urll.openConnection()).
I have tried threads, async tasks and syncronously calling the url with multiple methods like: URLConnection, HttpGet
This is difficult since you have to run the network request in the background(asynchronously).
So even though you schedule the network request to happen in the background it might/probably fail since you then destroy the Activity that sent it.
A different approach might be to save the message you want to send on file(synchronously) and then fire it later when the user start the app again.
A more sophisticated approach might be to start a Service (can live without an Activity being present in the foreground) and let that handle any network request.
As a note, I would however avoid doing large amount of work via Services because then the user will notice degraded performance.
Easy approach:
#Override
onDestroy(){
new Thread(new Runnable() {
#Override
public void run() {
ping();//your ping code here!
}
}).start();
super.onDestroy();
}
I've been using AsyncTask for some time already and it never stopped working after some time like in this case. After I open my app for the first time everything works fine and I can execute AsyncTask many times.
The problem is after I close my app and put device to stand still for a couple of minutes, AsyncTask becomes impossible to execute. Usually it takes for 1-2 seconds to load data, but in this case it takes for a couple of minutes.
This is my AsyncTask:
class MyAsyncTask extends AsyncTask<String, Void, ArrayList<MyObject>> {
private ProgressDialog dialog;
private FragmentActivity context;
public MyAsyncTask(FragmentActivity activity) {
context = activity;
dialog = new ProgressDialog(context);
}
protected void onPreExecute() {
this.dialog.setMessage("...");
this.dialog.show();
}
#Override
protected ArrayList<MyObject> doInBackground(String... params) {
HttpURLConnection connection = null;
ArrayList<MyObject> objects = null;
try {
URL url = new URL(params[0]);
connection = (HttpURLConnection) url.openConnection();
InputStream in = connection.getInputStream();
BufferedReader reader = new BufferedReader(
new InputStreamReader(in));
if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
return null;
}
String line;
objects = new ArrayList<MyObject>();
MyObject mo = new MyObject();
while ((line = reader.readLine()) != null) {
// Process data
}
reader.close();
} catch (Exception e) {
return null;
} finally {
if (connection != null)
connection.disconnect();
}
return objects;
}
#Override
protected void onPostExecute(ArrayList<MyObject> data) {
if (dialog.isShowing()) {
dialog.dismiss();
}
if (data == null) {
Toast.makeText(context, "fail", Toast.LENGTH_SHORT).show();
}
else {
}
}
}
One more thing I've noticed is that when I press back or home buttons on my device and go back on home screen, in LogCat I see this warning:
W/IInputConnectionWrapper(22155): showStatusIcon on inactive InputConnection
I thought that this warning only appears if I don't close my connection but connection.disconnect(); is always called inside finally block. This could maybe be a part of the problem.
What do you think could be a problem?
UPDATE1
Now I noticed that after a couple of minutes I receive the following exception:
java.net.SocketException: recvfrom failed: ETIMEDOUT (Connection timed out)
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.
I'm making an app that sends a string to a server over a socket and then reads the output after the server has processed that data. It worked perfectly when it was my foreground task, but I have since used AsyncTask to show a process dialog while the socket communication runs in the background, and things start breaking after I read the output from the server and then try to close the socket.
private class Progressor extends AsyncTask<String, Void, Void> {
ProgressDialog dialog;
protected void onPreExecute() {
dialog = ProgressDialog.show(ClearTalkInputActivity.this, "Loading..", "Analyzing Text", true, false);
}
protected Void doInBackground(String... strings) {
String language = strings[0].toLowerCase();
String the_text = strings[1];
Socket socket = null;
DataOutputStream dos = null;
DataInputStream dis = null;
try {
socket = new Socket(my_ip, port);
dos = new DataOutputStream(socket.getOutputStream());
dis = new DataInputStream(socket.getInputStream());
dos.writeUTF(language+"****"+the_text);
String in = "";
while (in.indexOf("</content>") < 0) {
in += dis.readUTF();
}
socket.close();
save_str(OUTPUT_KEY, in);
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
if (dos != null) {
try {
dos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (dis != null) {
try {
dis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
protected void onPostExecute() {
if (dialog.isShowing())
dialog.dismiss();
startActivity(new Intent (output_intent));
}
}
The recommended way in Android is to use one of the two included HttpClients:
Apache HTTP Client
HttpURLConnection
There is no need to use sockets directly. These clients do a lot to improve your experience.
Here is a blog article by the Android developers, that explain the basics: http://android-developers.blogspot.de/2011/09/androids-http-clients.html