make android AsynTask to wait for result - android

i want to implement a login activity. it checks user existance with a webservice.
EditText un=(EditText) findViewById(R.id.txtName);
EditText pass=(EditText) findViewById(R.id.txtPass);
WS ss=new WS();
String str=ss.execute("checkLogin",un.getText().toString(),pass.getText().toString()).get();
Intent in=new Intent(arg0.getContext(), Overview.class);
in.putExtra("username", str);
if(str=="No User")
Toast.makeText(getApplicationContext(), "ss", 300).show();
else
{
startActivity(in);
finish();
}
the problem is in "IF" section. "str" value sets after finishing code lines.
but i want to get "str" value then check for IF to run proper actions.

You need override onPostExecute method see below example
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
protected Long doInBackground(URL... urls) {
int count = urls.length;
long totalSize = 0;
for (int i = 0; i < count; i++) {
totalSize += Downloader.downloadFile(urls[i]);
publishProgress((int) ((i / (float) count) * 100));
}
return totalSize;
}
protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]);
}
protected void onPostExecute(Long result) {
showDialog("Downloaded " + result + " bytes");
}
}

The whole point of an asynchronous task is to not block synchronously. You have several options if you do want synchronous behavior:
Don't use AsyncTask in the first place (probably not a good idea if it is a long-running network call)
Put the code you want to run after the AsyncTask completes it's background work in the onPostExecute method, which will have access to the result of the data returned from the background method
Provide a callback to the AsyncTask that onPostExecute can call when it is finished (similar in concept to the previous option but more formal and robust to changes)
I prefer the last option, but it also takes more dev time to write than the other options.
Don't forget that an AsyncTask may do it's background work and/or finish after the activity has been finished and shut down, so make sure to check for that state appropriately before you start interacting with the UI.

If you are trying to do a network call you shouldn't use asynctask rather use loopj or google's volley library .
Asynctask is not meant for long network calls , having said that here's an example of asynctask class , code:
class AsyncTaskExample extends AsyncTask<Void, Integer, String> {
private final String TAG = AsyncTaskExample.class.getName();
protected void onPreExecute(){
Log.d(TAG, "On preExceute...");
}
protected String doInBackground(Void...arg0) {
Log.d(TAG, "On doInBackground...");
for(int i = 0; i<5; i++){
Integer in = new Integer(i);
publishProgress(i);
}
return "You are at PostExecute";}
protected void onProgressUpdate(Integer...a){
Log.d(TAG,"You are in progress update ... " + a[0]);
}
protected void onPostExecute(String result) {
Log.d(TAG,result);
}
}
Edit it as you wish and instanciate a new one in your code when you want to do the check up ,
Hope it helps

Related

AsyncTask and getting/updating Data

I can easily get data from the database.. But because Asynctask runs in the background, it has not downloaded the data before i call my update() method.
Example.
MyGetDataFromDatebaseCall();
UpdateSomething();
So here's my question. How can you make the UpdateSomething() method wait until the MyGetDatebaseCall() has downloaded alle the data?
I have made a Dialog window that pops up, so the user have to press okay to proceed and that works. I could also create 2 buttons so they call one method each. But they are such ugly solutions. I have also tried to send an instance of the Activity i was in, and making the AsyncTask class try and update the Activity class in the doInBackground, but apperently it cant be done?
You should call MyGetDataFromDatebaseCall() method in doInBackground() and after downloading all the data, you can call updateSomething() method in onPostExecute().
It will work fine.
Did you ever look at the documentation?
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
protected Long doInBackground(URL... urls) {
int count = urls.length;
long totalSize = 0;
for (int i = 0; i < count; i++) {
totalSize += Downloader.downloadFile(urls[i]);
publishProgress((int) ((i / (float) count) * 100));
// Escape early if cancel() is called
if (isCancelled()) break;
}
return totalSize;
}
protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]);
}
protected void onPostExecute(Long result) {
showDialog("Downloaded " + result + " bytes");
}
}

How to handle isCancelled in AsyncTask

I am trying to add this code to my doInBackGround so I can catch a flag that is being set when the user presses the back button
protected Long doInBackground(URL... urls) {
int count = urls.length;
long totalSize = 0;
for (int i = 0; i < count; i++) {
totalSize += Downloader.downloadFile(urls[i]);
publishProgress((int) ((i / (float) count) * 100));
// Escape early if cancel() is called
if (isCancelled()) break;
}
return totalSize;
}
This my doInBackGround and the code I use to set the flag for the asynctask to be canceled
#Override
public void onBackPressed()
{
/** If user Pressed BackButton While Running Asynctask
this will close the ASynctask.
*/
if (mTask != null && mTask.getStatus() != AsyncTask.Status.FINISHED)
{
mTask.cancel(true);
}
super.onBackPressed();
finish();
}
#Override
protected void onDestroy() {
// TODO Auto-generated method stub
/** If Activity is Destroyed While Running Asynctask
this will close the ASynctask. */
if (mTask != null && mTask.getStatus() != AsyncTask.Status.FINISHED)
{
mTask.cancel(true);
}
super.onDestroy();
}
#Override
protected void onPause() {
// TODO Auto-generated method stub
if (pDialog != null)
{
if(pDialog.isShowing())
{
pDialog.dismiss();
}
super.onPause();
}
}
class LoadAllData extends AsyncTask<String, String, String> {
protected String doInBackground(String... args) {
try {
Intent in = getIntent();
String searchTerm = in.getStringExtra("TAG_SEARCH");
String query = URLEncoder.encode(searchTerm, "utf-8");
String URL = "example.com";
JSONParsser jParser = new JSONParsser();
JSONObject json = jParser.readJSONFeed(URL);
try {
JSONArray questions = json.getJSONObject("all").getJSONArray("questions");
for(int i = 0; i < questions.length(); i++) {
JSONObject question = questions.getJSONObject(i);
String Subject = question.getString(TAG_QUESTION_SUBJECT);
String ChosenAnswer = question.getString(TAG_QUESTION_CHOSENANSWER);
String Content = question.getString(TAG_QUESTION_CONTENT);
The problem comes when I try to translate isCancelled into my asynctask. I get an error under Downloader that says "Downloader cannot be resolved" I also get one under publishProgress that says "The method publishProgress(String...) in the type AsyncTask is not applicable for the argument (int)" I'm jus tasking is somebody can help put the isCancelled into my AsyncTask. I have also done my research and seen that there are more than one way to use isCancelled in your code. I have realized that dealing with isCancelled can really be a hassle for somebody new to it.
1) To resolve error one make Downloader a public static data variable of the class.
2) Please make sure
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long>
is the class declaration
After you called cancel() isCancelled() will return true, and after your doInBackground returned onCancelled is executed instead of onPostExecute. The Parameter will issue an interrupt on the background thread, so your long-time operations are closed. However, I'd assume you catch that somewhere?
Hope this Helps..:)..
If it doesnt solve the error..Please post logcat details
From SDK:
Cancelling a task
A task can be cancelled at any time by invoking cancel(boolean).
Invoking this method will cause subsequent calls to isCancelled() to
return true. After invoking this method, onCancelled(Object), instead
of onPostExecute(Object) will be invoked after
doInBackground(Object[]) returns. To ensure that a task is cancelled
as quickly as possible, you should always check the return value of
isCancelled() periodically from doInBackground(Object[]), if possible
(inside a loop for instance.)
Also please use super.onpause() etc at the begining of the function block
Refer this:- link
In this case you will need to write a separate file for your Asynctask class. also make an interface callback.
you do not need to overide the onBackPress button, you just need to set your progressDialog to cancelable(True) and set onCancelListner(). here you can set a flag isCanceld = true;
the whole scenario is defined in this link.
android asynctask sending callbacks to ui
see the answer of Dmitry Zaitsev try this one and let me know if stuck in any where
hope this helps

using asynctask to speed up android app launch time

I have an app which load ads from two networks and sets a flash file to webview when started.This is making it too slow on startup, forums told me to use asynctask.Can some one make this code an asynctask.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
airpush=new Airpush(getApplicationContext());
airpush.startPushNotification(false);
airpush.startIconAd();
airpush.startDialogAd();
airpush.startAppWall();
mWebView = (WebView) findViewById(R.id.webview);
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.getSettings().setPluginsEnabled(true);
mWebView.setScrollBarStyle(WebView.SCROLLBARS_OUTSIDE_OVERLAY);
mWebView.setBackgroundColor(Color.parseColor("#000000"));
mWebView.loadUrl("file:///android_asset/game.swf");
AdView adView = (AdView)this.findViewById(R.id.adView);
adView.loadAd(new AdRequest());
It will be much more helpful for you to spend a little bit of time understanding the architecture of an AsyncTask than for someone to simply make one for you.
An AsyncTask is actually a fairly simple class to extend and use. An AsyncTask can, in its simplest form, be code that runs in the background (off the UI thread -- this is what causes lockup), but is set up to allow for some code to run in the background, some code to execute before/after, and some code to execute as a progress update if necessary.
You will need to create your own class that extends AsyncTask as shown below. Your task will take three parameters. The first will get passed into the doInBackground function that runs in the background, the second is a type for a parameter that can be passed into a progress update function, and the third is a type to be passed into your onPostExecute fn that runs on the UI thread after the background function has completed. In the simple example below I will not include types to be passed to a post execute function or a progress update function, so they will be of type Void.
private class YourTask extends AsyncTask<byte[], Void, Void> {
protected Long doInBackground(byte[]... data) {
//get the array
byte[] array = data[0];
//do something with it.
HERE IS WHERE YOU RUN YOUR CODE IN THE BACKGROUND THAT IS TAKING TOO LONG ON THE UI THREAD
//return null because this type needs to match the last type for returning to the postexec fn
return null;
}
}
When you want to run your task you call the following:
new YourTask().execute(someByteArray);
So oftentimes you can stick the code that is taking a long time into that doInBackground function, but you have to be careful because it is off the UI thread and some code does have to be run on the UI thread.
I would recommend doing some profiling to see what code specifically is choking up your UI thread, and run THAT in the background using an AsyncTask. You can do that by using DDMS in Eclipse and use method profiling. Another way would be to use the Debug class and call Debug.startMethodTracing("tracefilename"); when you want to start and Debug.stopMethodTracing();. You can read more about that here. However, your code does load a url (mWebView.loadUrl) so I would assume this may be a big bottleneck!
Just as an addendum, if you want a more in depth example of an AsyncTask, here is one I C&Pd from this useful documentation:
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
protected Long doInBackground(URL... urls) {
int count = urls.length;
long totalSize = 0;
for (int i = 0; i < count; i++) {
totalSize += Downloader.downloadFile(urls[i]);
publishProgress((int) ((i / (float) count) * 100));
// Escape early if cancel() is called
if (isCancelled()) break;
}
return totalSize;
}
protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]);
}
protected void onPostExecute(Long result) {
showDialog("Downloaded " + result + " bytes");
}
}
The above example has code to both exemplify updating progress on the UI during the background task as well as passing a parameter that is then used by the UI thread-running post execute fn.
I can't just make your code an AsyncTask but I can give you an example and some help. This is an example of AsyncTask
public class TalkToServer extends AsyncTask<String, String, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
}
#Override
protected String doInBackground(String... params) {
//do your work here
return something;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
// do something with data here-display it or send to mainactivity
}
All of your network stuff you will put in doInBackground() then if you need to update the UI you did that in the other methods. After finishing the network stuff you can update UI in onPostExecute().
This is how you would call the task
TalkToServer myAsync = new TalkToServer() //can add params if you have a constructor
myAsync.execute() //can pass params here for `doInBackground()` method
If it is an inner class of your MainActivity then it will have access to member variables of MainActivity. If its a separate class then you can pass context to constructor like
TalkToServer myAsync = new TalkToServer(this);
and create a constructor to accept Context and any other params you want
I strongly suggest going through the docs below and make sure you understand how it works. Maybe the biggest thing to understand when getting started is that doInBackground() doesn't run on the UI so you don't want to try and update any Views here but in the other AsyncTask methods or by passing data back to the MainActivity and update there
AsyncTask

How to notify activity about sync errors when using SyncAdapter

I have a table called student which I want to populate from the server. In my activity I show a progress bar and call ContentProvder.requestSync(Content URI of student..). Now if I understand correctly as per Virgil's talk I should add an observer on the ContentURI of the student to be notified later by the ContentProvider when the sync finishes. But what happens if say there was a network error. The student table will never be populated and my progress dialog will never be removed.
I understand the
"broadcast receiver approach"
mentioned in another thread but that deviates from Virgil's approach which I consider ideal.
Also on those lines why doesn't the requestSync allow to pass a ResultReceiver as part of the extras. Isn't that generally a Service talks back to an Activity?
A SyncAdapter is not meant to be used for this kind of scenario. SyncAdapter is meant for background sync of data, invisible to the user.
Your case sounds like perfect for a AsyncTask. With that you can use publishProgress() to update your progress bar while your network task happens in another thread. You can find a lot of information and examples on AsyncTask online.
Example from the link above:
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
protected Long doInBackground(URL... urls) {
int count = urls.length;
long totalSize = 0;
for (int i = 0; i < count; i++) {
totalSize += Downloader.downloadFile(urls[i]);
publishProgress((int) ((i / (float) count) * 100));
// Escape early if cancel() is called
if (isCancelled()) break;
}
return totalSize;
}
protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]);
}
protected void onPostExecute(Long result) {
showDialog("Downloaded " + result + " bytes");
}
}
run it by executing it like so:
new DownloadFilesTask().execute(url1, url2, url3);
Here is another example, with tutorial (simply found by google):
http://androidresearch.wordpress.com/2012/03/17/understanding-asynctask-once-and-forever/

Android with thread shows error

In the application i called the Thread in the alerdialog click listener.
It shows the Error "Force to close the application" in the Mobile Samsung pro.
but when i execute the same code in the another application then code works correctly...
It's probably because you're doing something wrong in the alerdialog click listener. Do the thing you're doing wrong right and it won't show the Error.
Do this below procedure help full in ur app
Android also provides something called AsyncTask which is specifically designed for running some stuff on a separate thread, and some on the UI thread. This automatically uses Android's threadpool, and if you do not have any reason to use an explicit separate thread, is an easy, clean way to go:
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
// Runs on a ThreadPool thread
protected Long doInBackground(URL... urls) {
int count = urls.length;
long totalSize = 0;
for (int i = 0; i < count; i++) {
totalSize += Downloader.downloadFile(urls[i]);
// Sends data to onProgressUpdate to run on the UI thread
publishProgress((int) ((i / (float) count) * 100));
}
return totalSize;
}
// Runs on the UI thread!
protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]);
}
// Runs on the UI thread!
protected void onPostExecute(Long result) {
showDialog("Downloaded " + result + " bytes");
}
}

Categories

Resources