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)
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 am trying to call an Restful api using following code. Now I want to show the progress(% of download). Is it at all possible? If, what change in code is needed for that?
BufferedReader reader=null;
try{
URL mUrl = new URL("http://dev.amazaws.com/formservice/rest/v1/registrationreports/registrationsbyproduct/132866/");
URLConnection conn = url.openConnection();
conn.setDoOutput(true);
OutputStreamWriter writer = new OutputStreamWriter(conn.getOutputStream());
writer.write( data );
writer.flush();
reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
StringBuilder sb = new StringBuilder();
String line = null;
while((line = reader.readLine()) != null)
{
sb.append(line);
}
String res = sb.toString();
}catch(Exception ex){
}finally{
try{
reader.close();
}catch(Exception ex) {}
}
Try this code, i have implemented this code in one of my application! You can get the idea how to show the percentage! and well This code actually download the JSON from server and saves it on mobile device.
public class LoginActivity extends Activity {
private ProgressDialog prgDialog;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.login_layout);
}
// Button Click function, on which you want to make restApi call
public void buttonClicked(View view){
new PrefetchData().execute();
}
private class PrefetchData extends AsyncTask<Void, Integer, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
// before making http calls
prgDialog = new ProgressDialog(LoginActivity.this);
prgDialog.setMessage("Downloading Data. Please wait...");
prgDialog.setIndeterminate(false);
prgDialog.setMax(100);
prgDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
prgDialog.setCancelable(false);
prgDialog.show();
}
#Override
protected Void doInBackground(Void... arg0) {
InputStream input = null;
OutputStream output = null;
HttpURLConnection connection = null;
try {
URL url = new URL("http://xyz/testJSON");
connection = (HttpURLConnection) url.openConnection();
connection.connect();
// expect HTTP 200 OK, so we don't mistakenly save error report
// instead of the file
if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
// Show ERROR
}
int fileLength = connection.getContentLength();
input = connection.getInputStream();
String extPath = Environment.getExternalStorageDirectory() + "/" + FILE_PATH;
// Environment.
File file = new File(extPath);
if(!file.exists()){
file.createNewFile();
}
output = new FileOutputStream(extPath);
byte data[] = new byte[4096];
long total = 0;
int count;
while ((count = input.read(data)) != -1) {
total += count;
if (fileLength > 0){
// only if total length is known
// publishing the progress....
publishProgress((int) (total * 100 / fileLength));
}
output.write(data, 0, count);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (output != null)
output.close();
if (input != null)
input.close();
} catch (IOException ignored) {
}
if (connection != null)
connection.disconnect();
}
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
// After completing http call
// will close this activity and lauch main activity
Intent i = new Intent(LoginActivity.this, MainActivity.class);
startActivity(i);
// close this activity
finish();
}
//Update the progress
#Override
protected void onProgressUpdate(Integer... values)
{
prgDialog.setProgress(values[0]);
}
}
As stated in this question you most often wont know the size of the stream in advance https://stackoverflow.com/a/1119346/2122552
The stated answer also links to an api to get Filesizes. But with a RESTful API you usually dont know the exact size of the Inputstream.
But, however, if you know the size you can break it down to use 100 as 100% and calculate the progress as (downloadedBytes/fileSizeInBytes * 100). Otherwise just use an indeterminate ProgressBar.
You can check the case and make the progressbar indeterminate when you dont know the size of the answer, and otherwise calculate the progress and update it like shown in the official documentation
I use AsnycTask to connect URL and parse the return xml:
class Connecting extends AsyncTask<String, String, String> {
private String URLPath = "";
private HttpURLConnection Connection;
private InputStream InputStream;
private boolean Return1 = false;
private int Return2 = -1;
public Connecting (String fn, String u) {
FileName = fn;
URLPath = u;
Connection = null;
InputStream = null;
Return1 = false;
Return2 = -1;
execute();
}
public boolean getReturn1() {
return Return1;
}
public int getReturn2() {
return Return2;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected String doInBackground(String... aurl) {
try {
URL url = new URL(URLPath);
Connection = (HttpURLConnection)url.openConnection();
Connection.setConnectTimeout(10000);
Connection.setReadTimeout(10000);
Connection.setDoInput(true);
Connection.setUseCaches(false);
Connection.connect();
InputStream = Connection.getInputStream();
}
catch (Exception e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String unused) {
super.onPostExecute(unused);
try {
InputStreamReader fsr = new InputStreamReader(InputStream);
BufferedReader br = new BufferedReader(fsr);
String line = "";
while((line = br.readLine()) != null) {
//parse Reture1 and Return2
}
}
catch(Exception e) {
e.printStackTrace();
}
Connection = null;
}
}
And I use below code to call it:
Connecting con = new Connecting(Name, URL);
System.out.println("Return1 " + con.getReturn1());
System.out.println("Return2 " + con.getReturn2());
It will get false and -1, which the init value.
And connect URL after print message.
I want to get the value which has connect success and parse from the xml.
How can I do it?
AsyncTask is a class that helps to run in background. You can use it if you want to access to remote server using for example HTTP connection.
In doBackground method you have to the the "heavy" task, the one that requires time and could block the UI. When you finish at the end of doBackground you have to return the value that is the result of the task.
Then in the onPostExecute you use this result to update for example the UI.
In your case it seems to me you aren't using correctly the AsyncTask. First of all you return null in doBackground and dont set return1 and return2 as you should.
And in onPostExecute you read the response while yuo should do it in doBackground.
There's another method you can override called onPreExecute that is called before doBackground method.
In my blog i've an example how to use AsyncBackground in this case and it could help you. If you like give a look here
The AsyncTask runs (as the name says) asynchronously to the main-thread.
If you want to happen something after the task is done, you have to put that code in the onPostExecute() method.
So you may put the System.out there.
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.