Issue
By using Android Studio, I need to design a mobile application that reads data from the website
and refreshes the data every minute. The problem I am facing is that AsyncTask in Android can be executed only once, so the next time I try to refresh the page and read data again from the website I am getting the following error message.
2018-12-03 14:48:21.308 5065-5065/com.samsung.asynctaskexample E/AndroidRuntime: FATAL EXCEPTION: main Process: com.samsung.asynctaskexample, PID: 5065 java.lang.IllegalStateException: Cannot execute task: the task has already been executed (a task can be executed only once) at android.os.AsyncTask.executeOnExecutor(AsyncTask.java:605) at android.os.AsyncTask.execute(AsyncTask.java:560) at com.samsung.asynctaskexample.MainActivity.updateHTML(MainActivity.java:45) at com.samsung.asynctaskexample.MainActivity.access$000(MainActivity.java:10) at com.samsung.asynctaskexample.MainActivity$1$1.run(MainActivity.java:37) at android.os.Handler.handleCallback(Handler.java:751) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:154) at android.app.ActivityThread.main(ActivityThread.java:6682) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1520) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1410)
What are the different ways that are available to fix this error message? Here is my code.
MainActivity.java
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
import java.util.Timer;
import java.util.TimerTask;
public class MainActivity extends AppCompatActivity implements AsyncResponse {
GetMethodDemo asyncTask = new GetMethodDemo();
TextView t1;
String website = "http://sspapi-dev.samsungrs.com/health";
private Timer autoUpdate;
int refresh_interval = 60000;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
t1 = findViewById(R.id.textview1);
asyncTask.delegate = this;
}
@Override
public void onResume() {
super.onResume();
autoUpdate = new Timer();
autoUpdate.schedule(new TimerTask() {
@Override
public void run() {
runOnUiThread(new Runnable() {
public void run() {
updateHTML();
}
});
}
}, 0, refresh_interval);
}
private void updateHTML() {
asyncTask.execute(website);
}
@Override
public void onPause() {
autoUpdate.cancel();
super.onPause();
}
@Override
public void processFinish(String output){
t1.setText(output);
}
}
JsonHelper.java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
public class JsonHelper{
HttpURLConnection connection;
String data;
public String getdatafromurl(String url){
try{
URL url1 = new URL(url);
connection = (HttpURLConnection) url1.openConnection();
connection.connect();
InputStream inputStream = connection.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
String line = "";
StringBuffer buffer = new StringBuffer();
while ((line = reader.readLine()) != null) {
buffer.append(line);
}
String result = buffer.toString();
return result;
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return data;
}
}
GetMethodDemo.java
import android.os.AsyncTask;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
public class GetMethodDemo extends AsyncTask<String, Void, String> {
public AsyncResponse delegate = null;
String server_response;
@Override
protected String doInBackground(String... strings) {
URL url;
HttpURLConnection urlConnection = null;
try {
url = new URL(strings[0]);
urlConnection = (HttpURLConnection) url.openConnection();
int responseCode = urlConnection.getResponseCode();
if(responseCode == HttpURLConnection.HTTP_OK){
server_response = readStream(urlConnection.getInputStream());
}
JsonHelper jsonhelper = new JsonHelper();
String data = jsonhelper.getdatafromurl(strings[0]);
return data;
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
delegate.processFinish(server_response);
}
// Converting InputStream to String
private String readStream(InputStream in) {
BufferedReader reader = null;
StringBuffer response = new StringBuffer();
try {
reader = new BufferedReader(new InputStreamReader(in));
String line = "";
while ((line = reader.readLine()) != null) {
response.append(line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return response.toString();
}
}
AsyncResponse.java
public interface AsyncResponse {
void processFinish(String output);
}
By the way, making use of
while(true) {
asyncTask.execute(website);
try
{
Thread.sleep(refresh_interval);
}
catch(InterruptedException ex)
{
break;
}
}
which I had first tried out initially, seems to be a bad idea since Thread.sleep function interferes with the performance of the other Android applications and even the overall Android operating system. I found out that making use of Timer in the way that I had described above is a good substitute for it.
Just I need to find out what changes are possible that I need to make to the code in order to read data from any given fixed website more than once, for example, to refresh at certain interval of period of time.
Solution
The easiest thing you can do is create a different GetMethodDemo
instance for each call to the server. To do so, you need to remove the asyncTask
field from your activity class and change your updateHTML()
method to something that looks like this:
private void updateHTML() {
GetMethodDemo asyncTask = new GetMethodDemo();
asyncTask.execute(website);
}
I just want to mention, that there are other alternatives to using timers and async tasks to achieve what you are aiming for. You could use something like WorkManager
+ Worker
, RxJava, etc. I advice you to take a look at some of those after getting your code to work.
Answered By - Danail Alexiev
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.