AsyncTask executes but only sometimes - java

So i use this code to call my AsyncTask
Log.d("before","make_connection");
new Make_Connection().execute();
Log.d("after","make_connection");
My class
private class Make_Connection extends AsyncTask<Void,Void,String>{
final int port = 4445;
#Override
protected void onPreExecute() {
Toast.makeText(KeyboardActivity.this,"This runs",Toast.LENGTH_LONG).show();
}
#Override
protected String doInBackground(Void... params) {
Log.d("Connection","Started");
Log.e("Connec","this runs");
try {
socket = new Socket(IP,port);
//dout = new DataOutputStream(socket.getOutputStream());
//dout.writeUTF("Connection Formed");
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
protected void onPostExecute(String result) {
Toast.makeText(KeyboardActivity.this,"Connection Made",Toast.LENGTH_SHORT).show();
}
}
Now i can see in the android monitor that these two are always execute
Log.d("before","make_connection");
Log.d("after","make_connection");
But half of the time i cannot see the output produced by
Log.d("Connection","Started");
Log.e("Connec","this runs");
Even though onPreExecute() runs properly everytime.
I have tested on two diffent mobilies running 7.1 and 7.0
Can someone please tell me why this is happening

Try:
new Make_Connection().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
instead of only
new Make_Connection().execute();
This is needed, because in Android SDK 13 or higher they run serially by default. So if you want to run more than one AsyncTask simultaneously, use executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR)
For more details, see explanation under order of execution from This docs

AsyncTasks are run sequentially by default. They all execute on the same executor. Taken from here https://developer.android.com/reference/android/os/AsyncTask.html
If you truly want parallel execution, you can invoke
executeOnExecutor(java.util.concurrent.Executor, Object[]) with
THREAD_POOL_EXECUTOR.

Related

Need to wait for file to be available

Below is my code where I need to convert my JSON file to an Excel file. Loading the JSON from another method will take some time, so I need to wait till the file is present.
public class converter2_ES {
#Test
public void main() throws Exception {
LocalDateTime date = LocalDateTime.now();
DateTimeFormatter dateformat = DateTimeFormatter.ofPattern("dd-MM-yyyy HH-mm-ss");
String formatedate =date.format(dateformat);
Workbook workbook = new Workbook(".//json_files//elastic_search.json");
//workbook.save(".//output-"+formatedate+".xlsx");
workbook.save(".//Excel_files//es_files//ES-"+formatedate+".xlsx");
System.out.println("Elastic_searchjson file converted successfully");
}
}
Question
In my test, the file .//json_files//elastic_search.json is actually written by another test. How can I make sure that this test is run after the test that writes the file to disk?
This question had to be extracted from the comments.
Answer
The answer is, it depends...
Generally speaking, tests should not have temporal coupling with one another. Meaning that test2() should not rely on the outcome or behavior of test1().
There are many ways of fixing this problem, it could be fixed by having your tests in two different classes each having their own particular setup() methods with an #BeforeEach annotation.
Another solution is to make sure that the tests run in the correct order. There are ways of adding order via the #Test annotation depending on which testing framework you're using.
You should make a async implementation that is, you should wait until previous task has been completed to proceed with next task, you can refer to this simple tutorial ANDROID - HTTP REQUEST USING ASYNCTASK TUTORIAL IN JAVA
Below is the code sample you can refer to:
public class MainActivity extends AppCompatActivity {
private Button btn;
private EditText time;
private TextView res;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
time = findViewById(R.id.in_time);
btn = findViewById(R.id.btn_start);
finalRes = findViewById(R.id.res);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
AsyncTaskRunner runner = new AsyncTaskRunner();
String sleepTime = time.getText().toString();
runner.execute(sleepTime);
}
});
}
private class AsyncTaskRunner extends AsyncTask<String, String,
String> {
private String resp;
ProgressDialog progressDialog;
#Override
protected void onPreExecute() {
progressDialog = ProgressDialog.show(MainActivity.this,
"PleaseWait",
"Loading"+time.getText().toString()+ "secs");
}
#Override
protected String doInBackground(String... params) {
publishProgress("TimeSpent...");
try {
int time = Integer.parseInt(params[0])*1000;
Thread.sleep(time);
resp = "Time Spent" + params[0] + "secs";
} catch (InterruptedException e) {
e.printStackTrace();
resp = e.getMessage();
} catch (Exception e) {
e.printStackTrace();
resp = e.getMessage();
}
return resp;
}
#Override
protected void onPostExecute(String result) {
// execution of result of Long time consuming operation
progressDialog.dismiss();
finalRes.setText(result);
}
}
}
If you want to wait for a file to be created by another program:
How to wait on file creation - which has examples on how to use the WatchService. However, note that you get an event to indicate that a file has been created, but you don't get one to say that file creation (i.e. writing) has completed. So, depending on how the save() method works, you will probably need to check the file size of modification timestamp to see when they stop changing.
From my reading of the javadocs, the WatchService should report file events for files created by the current program as well, but there may be better ways. For example, if you want to wait for a file to be created by another thread:
If you are using naked threads or thread subclasses, use Thread.join() to wait for the thread doing the creation to finish.
If you are using an ExecutorService rather than naked threads, keep the Future object returned when you submit a task and use it to detect when the task has completed.
If you are doing this in some test code, the WatchService may be overkill. A simple polling loop (with a sleep) that tests to see that the target file has been created may be sufficient.
These won't be appropriate if you code is part of (say) a Swing or JavaFX app. These have their own ways to perform a long running task and act on its completion. (If you simply wait for the task in in the UI event loop, you will block the event loop.
Android will be different again ...

Timed send on udp network failed for java.lang.IllegalMonitorStateException

I need to send data over ad UDP connection on a time basis (once every 20ms).
I tried using a Handler / Runnable / postDelayed() approach ... it was working fine until Android 9.0.
Now I need to use a different approach based on AsyncTask:
class SendCommandTask extends AsyncTask {
#Override
protected Object doInBackground(Object[] objects) {
try {
do{
sendCommands();
wait(UPDATE_DELAY);
} while(!isCancelled());
}
catch (Exception e)
{
Log.e(this.getClass().getName(), e.getMessage());
}
return null;
}
}
but it fails throwing an java.lang.IllegalMonitorStateException .
I know the problem is the wait() call but I cannot find a simple way to achieve the same result.
The solution to this issue is to simplify doInBackground method executing just a single sendCommands() call:
class SendCommandTask extends AsyncTask<Object, Void, Void> {
#Override
protected Void doInBackground(Object[] param) {
try {
sendCommands();
}
catch (Throwable e)
{
Log.e(this.getClass().getName(), e.getMessage());
}
return null;
}
}
AsyncTask objects are instantiated and executed trough a recurring thread structure:
timerTask = new Runnable() {
#Override
public void run() {
new SendCommandTask().execute();
sendCommandsTimerHandler.postDelayed(this, UPDATE_DELAY);
}
};
in this specific case a simple timer.
Please note that all this has been wrote to avoid rising of exceptions due to use of network bound resources inside SendCommands() calls. In my previous code these calls where executed straight inside the very same timer as above. Now I have to wrap everything like this... looks like a non-sense to me.

Multi-threading in Android

I'm new to Android and Java. I'm trying to download 1000 plus images. I don't want to do that serially in a UI thread as that will be slow. Hence, I implemented multi-threading using thread and runnable in the below manner.
The for-loop will be called 1000 plus times. So is it an efficient way of achieving it? Will the OS manage the thread pool by its own?
private void syncS3Data() {
tStart = System.currentTimeMillis();
try {
for (final AWSSyncFile f : awsSyncData.getFiles()) {
new Thread(new Runnable() {
#Override
public void run() {
beginDownload(f);
}
}).start();
}
} catch (Exception ex) {
progressDialog.dismiss();
showMessage("Error:" + ex.getStackTrace().toString());
}
}
for Sure you can't do that in MainThread (UI Thread) because if you did, the application will not be responding.. and then it will be killed by system, you can use AsyncTask class in order to do what do you need but i prefer to use intentservice
However you have to use Intentservice it's a worker thread (long operation) but be noted intentservice will not execute anything until it finish the current task, if you need to download it in parallel then you have to use Service it works with UI Thread so you need asyncTask in order to perform the action but make sure of calling stopSelf() unlike intentService it will be stopped once it finish
Instead of creating threads for each download, create one thread and use that for downloading all images.
You can use AsyncTask Refer: https://developer.android.com/reference/android/os/AsyncTask.html
private class DownloadFilesTask extends AsyncTask<SomeObject, Integer, Long> {
protected Long doInBackground(SomeObject... objs) {
for (final AWSSyncFile f : obj.getFiles()) {
beginDownload(f);
}
}
protected void onPostExecute(Long result) {
//Task Completed
}
new DownloadFilesTask().execute(someObj);
I had developed an e-commerce app before and have encountered a similar problem in which I had to download some 200+ images for each category.The way I did it was using a loop within an AsyncTask and after each download was completed the image was displayed at the relevant place using the onProgessUpdate() function.I can't share the actual code,so i will give a skeleton example.
public class DownloadImages extends AsyncTask<String,String,String>
{
File image;
protected String doInBackground(String... params)
{
//download the image here and lets say its stored in the variable file
//call publishProgress() to run onProgressUpdate()
}
protected void onProgressUpdate(String... values)
{
//use the image in variable file to update the UI
}
}

AsyncTask in android 4.2.2

I'm trying to execute some code parallel with threads using async task.
But for some reason in android 4.2.2 doesn't work.
I have this code which is in main class:
new XmlDownloader();
task=new SendTask().execute("");
and the following classes:
private class SendTask extends AsyncTask<String,String,String>{
#Override
protected void onPreExecute(){
}
#Override
protected String doInBackground(String...strings){
while(true){
Log.w("outside", "hello");
}
}
return strings[0];
}
#Override
protected void onPostExecute(String country){
}
}
and
public class XmlDownloader extends Activity {
public XmlDownloader(int pos) {
DownloaderTask task = new DownloaderTask();
task.execute("");
}
private String downloadXml(String s,int pos1) {
return null;
}
private class DownloaderTask extends AsyncTask<String, Void, String> {
public DownloaderTask() {
}
#Override
// Actual download method, run in the task thread
protected String doInBackground(String... params) {
while(true){
Log.w("down", "asdasdasssasdasdasdasd");
if(isCancelled())
return null;
};
return null;
}
#Override
// Once the image is downloaded, associates it to the imageView
protected void onPostExecute(String bitmap) {
}
}
}
In android 2.3.3 the logcat shows this sequence
Log.w("down", "asdasdasssasdasdasdasd");
Log.w("down", "asdasdasssasdasdasdasd");
Log.w("down", "asdasdasssasdasdasdasd");
Log.w("outside", "hello");
Log.w("outside", "hello");
Log.w("down", "asdasdasssasdasdasdasd");
but in android 4.2.2 only shows
Log.w("down", "asdasdasssasdasdasdasd");
Log.w("down", "asdasdasssasdasdasdasd");
Log.w("down", "asdasdasssasdasdasdasd");
Log.w("down", "asdasdasssasdasdasdasd");
Log.w("down", "asdasdasssasdasdasdasd");
Any ideas why threads don't work?
Using AsyncTask may not give you the true parallelism that you need. Across different versions of Android, the number of AsyncTasks that can run simultaneously has been changed from 1 to 5 and then back to 1 (If I'm not wrong).
https://github.com/android/platform_frameworks_base/commits/master/core/java/android/os/AsyncTask.java
https://groups.google.com/forum/?fromgroups#!topic/android-developers/8M0RTFfO7-M
AsyncTasks are backed by a ThreadPool over which you have no control. If AsyncTask doesn't fit your needs, is to use Services or Loopers or build your own ThreadPoolExecutor. AsyncTask is not designed to loop idefinitely, that is to be a server or a service.
So what is happening is that in your Android version only the first enqueued thread from the pool is executed and since it doesn't terminate (they will be run sequentially), the second one never starts.
This has to do with the way AsyncTasks have evolved since their conception in API 3. In API 3, AsyncTasks(plural) were executed serially. This was changed to a pool of threads, allowing multiple AsyncTasks to run in parallel (API 4(DONUT)). But, starting HONEYCOMB(API 11), AsyncTasks are back to being executed serially.
Looking at the output you have provided, both SendTask & DownloaderTask execute in parallel in case of 2.3.3 which is > DONUT and < HONEYCOMB. But, in case of 4.2.2, serial execution of AsyncTasks takes place. Since DownloaderTask is executed first, SendTask waits for it to finish execution(which won't happen thanks to while(true)) --> hence, no output.
Since API 11, you have a choice over whether your AsyncTasks run serially or in parallel. For serial execution, use execute(Params... params). For parallel execution, look into executeOnExecutor(Executor exec, Params... params).

AsyncTasks do not get collected causing other AsyncTasks to not run

My app uses a lot of AsyncTasks. It is a web app after all. And when I keep track of the Debug tab, I notice every AsyncTask says running behind it and after 5 AsyncTasks, I can't start any AsyncTasks. I fixed it by changing the executor to THREAD_POOL_EXECUTOR which allows 15 threads to be pooled. But the AsyncTasks still show as running.
The AsyncTasks all have InputStreams in them and BufferedReaders in them to read the JSON, but I never call the close() method on the Streamers and Readers. Could this be it, or will the AsyncTask be collected after it's finished no matter what?
If that's the deal, then why can't I run more than 5 AsyncTasks in my app?
Seeing as I put a bounty on it, I will explain this more explicitly
The AsyncTasks all go through their methods. All of them are built the same exact way, except with different BasicNameValuePairs. I am 100% sure there is no easy mistake made in the code.
Here is an example of one of the AsyncTasks:
private class RunningEvent extends AsyncTask<Void, Void, Response> {
#Override
protected void onPreExecute() {
if (Constants.isOnline(getApplicationContext())) {
super.onPreExecute();
} else {
Toast.makeText(getApplicationContext(),
"No internet connection", Toast.LENGTH_LONG).show();
return;
}
}
#Override
protected Response doInBackground(Void... empty) {
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost(URL);
try {
List<NameValuePair> values = new ArrayList<NameValuePair>(5);
values.add(new BasicNameValuePair("tag", "eventRunning"));
values.add(new BasicNameValuePair("userid", String
.valueOf(response.user.userid)));
post.setEntity(new UrlEncodedFormEntity(values));
HttpResponse httpresponse = client.execute(post);
HttpEntity entity = httpresponse.getEntity();
InputStream stream = entity.getContent();
Log.i("MenuActivity",
"Input streamed, parsing Gson for existing events");
Gson gson = new Gson();
Reader reader = new InputStreamReader(stream);
eventresponse = gson.fromJson(reader, Response.class);
return eventresponse;
} catch (Exception e) {
e.printStackTrace();
Log.e("RunningEvent", "Error sending data to Server");
}
return null;
}
#Override
protected void onPostExecute(Response result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
Log.i("MenuActivity", "Binding button");
if (eventresponse != null) {
if (eventresponse.success == 1) {
eventresponse.user = response.user;
bActivity.setOnClickListener(new OnClickListener() {
public void onClick(View arg0) {
Intent i = new Intent("com.xxx.xxx.EVENT");
i.putExtra("response", eventresponse);
running = false;
switcher.cancel(true);
MenuActivity.this.finish();
startActivity(i);
}
});
} else {
bActivity.setText("Nieuw activity");
bActivity.setOnClickListener(new OnClickListener() {
public void onClick(View arg0) {
Intent i = new Intent("com.xxx.xxx.NEWEVENT");
i.putExtra("response", response);
running = false;
switcher.cancel(true);
MenuActivity.this.finish();
startActivity(i);
}
});
}
} else {
Log.i("RunningEvent", "Response is null");
}
}
}
The example above is the sometimes gets runned as the 6th AsyncTask and it will never enter the doInBackground() method. I believe this is the 5 Thread limit of the SERIAL_EXECUTOR. I "fixed" the problem by putting most AsyncTasks in THREAD_POOL_EXECUTOR, but this is just avoiding it.
What could be the reason that these AsyncTasks never stop running and clogging up the Executor?
android.os.AsyncTask come with two built-in executor. if using SERIAL_EXECUTOR, there is no threadpool and all AsyncTask get execute one at a time in serial order. if using THREAD_POOL_EXECUTOR (I suppose this is what you refer in the question), this allows up to maximum 128 AsyncTask get execute in parallel.
The number 5 you refer and see from debugging is the corePoolSize of underlying threadpool (AKA. THREAD_POOL_EXECUTOR), which is different from maximumPoolSize. check out AsyncTask source code and see how threadpool is implemented:
private static final int CORE_POOL_SIZE = 5;
private static final int MAXIMUM_POOL_SIZE = 128;
private static final int KEEP_ALIVE = 1;
... ...
/**
* An {#link Executor} that can be used to execute tasks in parallel.
*/
public static final Executor THREAD_POOL_EXECUTOR
= new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,
TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);
Check out ThreadPoolExecutor API to see what is the default threadpool behavior created by calling this constructor. Generally speaking, corePoolSize is the number of threads to keep in the pool, even if they are idle, unless allowCoreThreadTimeOut is set.
Those 5 AsyncTask you see in debug are actually on core threads which are finished and become idle but never terminated, you can alter this behavior by calling ThreadPoolExecutor.allowCoreThreadTimeOut(boolean).
More story on SERIAL_EXECUTOR
I said SERIAL_EXECUTOR does not use threadpool, this is not true. SERIAL_EXECUTOR is indeed delegate the real work to THREAD_POOL_EXECUTOR, but using ArrayDeque to control the submission of next tasks (next task is submitted iff the previous task is finished), check out the source:
private static class SerialExecutor implements Executor {
final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
Runnable mActive;
public synchronized void execute(final Runnable r) {
mTasks.offer(new Runnable() {
public void run() {
try {
r.run();
} finally {
scheduleNext();
}
}
});
if (mActive == null) {
scheduleNext();
}
}
protected synchronized void scheduleNext() {
if ((mActive = mTasks.poll()) != null) {
THREAD_POOL_EXECUTOR.execute(mActive);
}
}
}
So whatever you use SERIAL_EXECUTOR or THREAD_POOL_EXECUTOR, there are always 5 core threads shown in threadpool even they are finished and become idle. However, number of core thread (configured by corePoolSize) is not the number of threads (configured by maximumPoolSize) currently running in threadpool.

Categories

Resources