Android. AsyncTask. Paralell using of two AsynkTask in main Activity - android

I try to start two AsyncTask in MainActivity's onCreate function
My task is to start them same time but I look that Authorization process start after Directory Scan process has completed. Why?
public class MainActivity extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
task1 = new MyTask1();
task1.execute(); // Asynch ???
task2 = new MyTask2();
task2.execute(); // Asynch ???
class MyTask1 extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
try {
// Disk scan process with using some functions from MainActivity
DiskScanProcess();
} catch (InterruptedException e) {
}
return null;
}
}
class MyTask2 extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
try {
// Authorizatin process with using some functions from MainActivity
AuthorizationProcess();
} catch (InterruptedException e) {
}
return null;
}
}
}

The documentation for AsyncTask, in the section titled "Order of execution", explains that "Starting with HONEYCOMB, tasks are executed on a single thread to avoid common application errors caused by parallel execution". If you want multiple tasks to execute in parallel, invoke them with executeOnExecutor().

Related

two different AsyncTask methods are waiting for each other

I don't know how to tell the problem.
I have two AsyncTask methods. doAreYouStanding and StartTimeout, when I'm running both in MainActivity
if StartTimeout in if I wait 10 seconds, the other method is waiting.
Why is this startTimeout thread pausing my other method?
doAreYouStanding in doInBackground works after waiting onPreExecute for 10 seconds
new doPopup().execute((Void) null);
// new StartTimeout().execute((Void) null);
private class doAreYouStanding extends AsyncTask<Object, Object, Void> {
#Override
protected void onPreExecute() {
Log.e("YHACKUP", "onPreExecute");
super.onPreExecute();
}
#Override
protected Void doInBackground(Object... objects) {
Log.e("YHACKUP", "doInBackground");
return null;
}
}
private class StartTimeout extends AsyncTask<Object, Object, Void> {
#Override
protected void onPostExecute(Void aVoid) {
if (!(ActivitySplash.this).isFinishing()) {
layout_timeout.setVisibility(View.VISIBLE);
}
super.onPostExecute(aVoid);
}
#Override
protected Void doInBackground(Object... objects) {
// try {
// Thread.sleep(10000);
// } catch (Exception e) {
// }
return null;
}
}
I'm sorry if my english is bad
By default async tasks run serially. so Intil, the first asyncTask gets completed, second asyntask will not be started. In order to run paelelly, use executeOnExecutor method
new doPopup().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);

Is Async Task the best for downloading files above 1 mb

I am running a book services app on android where the user downloads the book onto his device.The book files are 1mb and above.
Can Async Task be considered as the best practice for this kind of operation.
Are there any other approaches to performing downloads in the background thread.
Please Advice.
Generally it is beleived that AsyncTask is not meant for long running tasks, but sometimes it is a simple way to perform a simple task (no matter how much time it will take). But the thing is,some of the developers perform it in a wrong way.
public class MainActivity extends Activity {
#Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
// Somewhere the AsyncTask is started
public class MyAsyncTask extends AsyncTask<Void, Void, String> {
#Override protected String doInBackground(Void... params) {
// Do work
return result;
}
#Override protected void onPostExecute(String result) {
Log.d("MyAsyncTask", "Received result: " + result);
}
}
}
The Problem with the above code is, When you start an AsyncTask inside an Activity and you rotate the device or any configuration change happens, the Activity will get destroyed and a new instance will be created. But the AsyncTask will not die and keep on going until it completes. Problems1) Since activities are heavy, this could lead to memory issues if several AsyncTask are started.2) Another issue is that the result of the AsyncTask could be lost, if it's intended to act on the state of the activity.
So we need to fix two problems
1) Activity should not be kept in memory when destroy by the framework.
2) Result of the AsyncTAsk should be delivered to the current Activity Instance.
And to Solve these Problems we need otto http://square.github.io/otto/
To use otto create a MyBus.java which we have to use it as a singleton
public class MyBus {
private static final Bus BUS = new Bus();
public static Bus getInstance() {
return BUS;
}
}
Create a AsyncTaskResultEvent.java file
public class AsyncTaskResultEvent {
private String result;
public AsyncTaskResultEvent(String result) {
this.result = result;
}
public String getResult() {
return result;
}
}
Now in your MainActivity, Do AsyncTask
public class MyAsyncTask extends AsyncTask<Void, Void, String> {
#Override protected String doInBackground(Void... params) {
Random random = new Random();
final long sleep = random.nextInt(10);
try {
Thread.sleep(sleep * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "Slept for " + sleep + " seconds";
}
#Override protected void onPostExecute(String result) {
MyBus.getInstance().post(new AsyncTaskResultEvent(result));
}
}
Now the Activity that starts the AsyncTask will get the result later.
To fix the memory leak problem add the below code in MainActivity
#Override protected void onDestroy() {
MyBus.getInstance().unregister(this);
super.onDestroy();
}
#Subscribe public void onAsyncTaskResult(AsyncTaskResultEvent event) {
Toast.makeText(this, event.getResult(), Toast.LENGTH_LONG).show();
}
and put this line of code in your OnCreate Method
MyBus.getInstance().register(this);
Now If a configuration change happens we'll automatically be notified of the result in the new Activity instance since it's registered to the event bus.

multithreading UI : exceptionininitializererror and runtime exception android

I'm trying to make multithreading but I've got this stacktrace on few smartphones (SGS2) :
java.lang.ExceptionInInitializerError
at com.android.bordeaux.code.model.AnnouncersContainer.setLoudArrayFromJSON_online(AnnouncersContainer.java:68)
at com.android.bordeaux.code.SplashscreenActivity_Second$1.run(SplashscreenActivity_Second.java:55)
Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
at android.os.Handler.<init>(Handler.java:121)
at android.os.AsyncTask$InternalHandler.<init>(AsyncTask.java:421)
at android.os.AsyncTask$InternalHandler.<init>(AsyncTask.java:421)
at android.os.AsyncTask.<clinit>(AsyncTask.java:152)
... 2 more
Here is my main activity (splashscreen) wich is making wait during few seconds in order to wait my asynctask finish:
public class SplashscreenActivity_Second extends Activity
{
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.splashscreen_second);
// thread
Thread splashThread = new Thread()
{
#Override
public void run()
{
try
{
int waited = 0;
if (isInternetOn())
{
// Here I'm making my asynctask !!
AnnouncersContainer.setLoudArrayFromJSON_online(getApplicationContext());
while (waited < 5000)
{
sleep(50);
waited += 40;
}
}
else
{
AnnouncersContainer.setLoudArrayFromXML_local(getApplicationContext());
while(waited < 5000)
{
sleep(50);
waited += 60;
}
}
}
catch( InterruptedException e )
{
e.printStackTrace();
}
finally
{
Intent intent_to_tabhost = new Intent(SplashscreenActivity_Second.this, MyTabActivity.class);
startActivity(intent_to_tabhost);
finish();
}
}
};
splashThread.start();
}
}
Here is my asynctask :
public class DownloadAnnouncers extends AsyncTask<Void, Integer, Boolean>
{
public static Boolean loadFinished = false;
//JSON variables..
private static String url = null;
Context context;
public DownloadAnnouncers(Context context)
{
this.context = context;
}
#Override
protected void onPreExecute()
{
super.onPreExecute();
}
protected Boolean doInBackground(Void... params)
{
// fine retrieving all my JSON data in a global array..
}
#Override
protected void onPostExecute(Boolean downloadedArray)
{
super.onPostExecute(downloadedArray);
}
}
I know the problem is that I'm making multithreading in the UI but someone can tell me how to delete my looping thread and replacing it just with onPostExecute() method of my Asynctask ?? (it could be better to wait for asynctask finishes rather than making wait..)
Or may be help me to correct this bug with multithreading..
EDIT :
my asynctask :
public class DownloadAnnouncers extends AsyncTask<Void, Integer, Boolean>
{
public static Boolean loadFinished = false;
//JSON variables..
private static String url = null;
Context context;
public DownloadAnnouncers(Context context)
{
this.context = context;
}
#Override
protected void onPreExecute()
{
super.onPreExecute();
}
protected Boolean doInBackground(Void... params)
{
// fine retrieving all my JSON data in a global array..
}
#Override
protected void onPostExecute(Boolean downloadedArray)
{
super.onPostExecute(downloadedArray);
Intent intent_to_tabhost = new Intent(context, MyTabActivity.class);
intent_to_tabhost.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent_to_tabhost);
}
}
But now if I press cancel button I'm returning to my splashscreen activity.. and I cannot do ctx.finish() in onPostExecute method..
You can't create a Handler inside a Thread that has not called Looper.prepare(), just as your Error message says:
Can't create handler inside thread that has not called Looper.prepare()
The Handler is created within the AsyncTask, so it's not something you might see at first.
If you want to keep your code as it is you would fix it by moving the creation of the AsyncTask to outside your custom Thread.
However, there is no need for you to create the thread, you can just create your AsyncTask in the ui thread (It will run on it's own thread so it won't lock your phone while working), and perform any action you want after the task is complete in the onPostExecute-method.
class ExampleAsync extends AsyncTask<Void, Integer, Boolean>
{
public static Boolean loadFinished = false;
//JSON variables..
private static String url = null;
Context context;
public DownloadAnnouncers(Context context){
this.context = context;
}
protected Boolean doInBackground(Void... params){
// fine retrieving all my JSON data in a global array..
}
#Override
protected void onPostExecute(Boolean downloadedArray){
Intent intent_to_tabhost = new Intent(context, MyTabActivity.class);
startActivity(intent_to_tabhost);
}
}
And in your Activity:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.splashscreen_second);
AsyncTask myTask = new ExampleAsync(this);
myTask.execute();
}
Instead of waiting for the asyncTask , use the onPostExecute , which is called on the UI thread only after the task has finished.
You should also cancel the task if the activity was destroyed (for example if the user has pressed the back button while the splash screen is shown) .

Executing two asynctask in in two different classes

I have 2 AsyncTasks in two different classes but the problem is when the first is do in backgroung state the second is not executed. The first asyncTask if preformed in loop because it needs to update every 5 seconds the new data. If i stop the task (condition = flase) the second one works perfectly.
First class:
public class MapScreen extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_map_screen);
UpdateUserCords updateUC = new UpdateUserCords();
updateUC.execute();
}
class UpdateUserCords extends AsyncTask<String, Void, String>
{
#Override
protected String doInBackground(String... params) {
while(condition)
{
//some code in loop...
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return null;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
}
}
}
Second class:
public class Groups extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_groups);
getGroups getGr = new getGroups();
getGr.execute(); //not executing, no error or crash
}
class getGroups extends AsyncTask<String, Void, String>
{
ArrayList<HashMap<String, String>> menuItems = new ArrayList<HashMap<String, String>>();
#Override
protected String doInBackground(String... params) {
//some code...
return null;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
}
}
}
After Android API 11, AsyncTasks started to run on serial executor by default, that means that only one task is running at a time. To get the behavior of prior to API 11, which is running on ThreadPoolExecutor, you'll need to specify it in the code like this:
if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.HONEYCOMB) {
myTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
else {
myTask.execute();
}
Please take a look here for more information:
http://commonsware.com/blog/2012/04/20/asynctask-threading-regression-confirmed.html
Good luck!
P.S. It's not recommended to use AsyncTask for an infinite thread, AsyncTask purpose is to do a Task on the background, not to run forever, so if you want an infinite thread, I think you should create it as a Thread and not as an AsyncTask.
You asynctasks are in two different activities.
Only one activity is active at any time.
Both classes extend Activity and only one of them is running at the same time.
If you want a task to be execute longer than the lifetime of an activity, you have to wrap it into an Service

How to cancel an Android AsyncTask after a certain amount of time? (Eg. 10 seconds)

I want to use a AsyncTask to check an InetAddress, such as in the code below. The variable tempInet is a global variable that indicates whether the website was contactable or not.
I begin the AsyncTask with the code... new InetAsyncTask().execute("www.facebook.com");
My problem is that I want the AsyncTask to cancel itself after (say) 10 seconds.
Some other questions suggest using the get(10, TimeUnit.SECONDS) method. I would like to do this but not sure where/how to put the get method. With execute? In the doInBackground method?
Also, does the get() method block the main thread? If it does, what is the point of it?
Any help appreciated.
class InetAsyncTask extends AsyncTask<String, String, Boolean> {
#Override
protected Boolean doInBackground(String... params) {
try {
InetAddress.getByName("www.facebook.com");
return true;
} catch (UnknownHostException e) {
return false;
}
} //end doInBackground function
protected void onPostExecute(Boolean... result) {
tempInet = result[0];
}
} //end class
Related Questions
Android - Setting a Timeout for an AsyncTask?
stop async task after 60 second
Android Developers AsyncTask Documentation
http://developer.android.com/reference/android/os/AsyncTask.html
You should make a handler which cancels the Asynctask (http://developer.android.com/reference/android/os/AsyncTask.html#cancel(boolean))
Send a delayed message to this Handler like:
Handler.sendMessageDelayed(msg, delayMillis)
private android.os.Handler mHandler = new android.os.Handler() {
#Override
public void handleMessage(Message msg) {
(Your AsyncTask object).cancel(true);
}
}
To answer your question. The code to use with get() is the following:
Boolean isHost = new AsyncTask<String, Void, Boolean>() {
#Override
protected Boolean doInBackground(String... params) {
try {
InetAddress.getByName(params[0]);
return true;
} catch (UnknownHostException e) {
return false;
}
}
}.execute("www.facebook.com").get(PING_TIME, TimeUnit.MILLISECONDS);
The get method blocks the caller thread as long as the result needs to be returned. You should therefore only use it in test situations. If you want to get an asynchronous answer start it as follows (this is one of my examples, you'll have to change it for your purpose):
private AsyncTask<Void, Void, Boolean> mAsyncTask;
private android.os.Handler timeHandler = new android.os.Handler() {
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
// react here or...
mAsyncTask.cancel(true);
}
};
public void pingServer() {
timeHandler.sendEmptyMessageDelayed(1, PING_TIME);
mAsyncTask = new AsyncTask<Void, Void, Boolean>() {
#Override
protected Boolean doInBackground(Void... params) {
// stop the time handler
timeHandler.removeMessages(1);
return restService.pingServer();
}
#Override
protected void onPostExecute(Boolean isOnline) {
super.onPostExecute(isOnline);
// use result after execution (e.g.: send to callback)
}
#Override
protected void onCancelled(Boolean aBoolean) {
super.onCancelled(aBoolean);
// ...react here
}
}.execute();
}

Categories

Resources