This is my class that i have extended from Asynctask:
public class HttpAsyncTaskSendData extends AsyncTask<String, Void, String> {
public interface SendDataCallback {
void onComplete(AsyncTask task,String nidSave, String guid);
void onError(String msg);
}
...
#Override
protected String doInBackground(String... urls) {
Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
return PostJson.POST(urls[0], urls[1]);
}
#Override
protected void onPostExecute(String result) {
if (result != null) {
...
dataCallback.onComplete(this,res.getString("NidSave"), guid);
} else {
dataCallback.onError("No response from server");
}
}
....
}
I am using this class in my activity like this:
sendDataQueue.add(httpAsyncTaskSendData = new HttpAsyncTaskSendData(cur.getString(cur.getColumnIndex("Guid")),
cur.getString(cur.getColumnIndex("SendStateGps")), datasource, database1
, Housing, new HttpAsyncTaskSendData.SendDataCallback() {
#Override
public void onComplete(AsyncTask task ,String nidSave, String guid) {
if (task.getStatus().equals(AsyncTask.Status.FINISHED) &&
!nidSave.equals("00000000-0000-0000-0000-000000000000")) {
sendDataQueue.remove(task);
} else {
queueHasError = true;
}
if (!queueHasError) {
if (sendDataQueue.size() == 0) {
SendGps(nidSave, guid);
}
}
}
#Override
public void onError(String msg) {
queueHasError = true;
toastError(DetailsActivity.this, msg);
}
}).executeOnExecutor((AsyncTask.THREAD_POOL_EXECUTOR),
AppUtil.getConfig(DetailsActivity.this,
MainActivity.SETTING_GEO_SERVICE) + "SaveVisit/",
json.toString()));
My question is why on onComplete callback when i check Asyncktask status , this is in Running mode? and it is not in Finnish.
My onComplete callback called on onPostExecute and in this section my task should be finished its job!!! but still is running? What's is happen and what's my problem?
onPostExecute is not yet finished, thus the state of the AsyncTask is not FINISH
AsyncTask.Status
FINISHED
Indicates that AsyncTask.onPostExecute(Result) has finished.
Related
I created an AsyncTask to fetch scores. It shows the progressdialog for a split-sec and then disappears. The doInBackground method never gets executes. This task is called inside a fragment.
private class GetScore extends AsyncTask<String,String,String> {
#Override
protected void onPreExecute() {
final ProgressDialog show = progressDialog.show(getActivity(), "", yourName);
super.onPreExecute();
}
#Override
protected String doInBackground(String... args) {
scoreMap = ScoreCalc.getEngScore(yourName);
// Toast.makeText(LoveActivity.this, engageMap.toString(), Toast.LENGTH_SHORT).show();
return null;
}
#Override
protected void onPostExecute(String img) {
}
}
.
.
.
.
.
.
.
private void confirmYes() {
String s =mEditText.getText().toString();
if(s.equals(""))
return;
new GetScore().execute();
}
Help?
use this asynctask class instead of your class.
public class GetScore extends AsyncTask<String, Void, String>
{
String method;
#Override
protected String doInBackground(String... arg0)
{
method = arg0[0];
return getData.callWebService(arg0[0], arg0[1]);
}
protected void onPostExecute(String xmlResponse)
{
if(xmlResponse.equals("") )
{
try{
if(progDialog!=null && progDialog.isShowing()){
progDialog.dismiss();
}
}catch(Exception ex){}
Toast.
}
else
{
if (method.equals("methodname"))
{
MethodName(xmlResponse, "ResponseTag");
try{
if(progDialog!=null && progDialog.isShowing()){
progDialog.dismiss();
}
}catch(Exception ex){}
//What Ever Want to Do
}
}
}
}
}
I found many subject about but I can't get a solution, I'm doing a soap request in doInBackground method of asyncTask, and I want to get an Integer to know if the process is done, here I call my asyncTask:
Simulation.AsyncSoapCall task = new Simulation.AsyncSoapCall();
try {
Integer taskResult = task.execute().get();
} catch (Exception e) {
e.printStackTrace();
}
My AsyncTask class:
private class AsyncSoapCall extends AsyncTask<Void, Void, Integer> {
Integer result;
Boolean isInternetPresent = false;
Boolean isUrlAvailable = false;
ConnectionDetector cd;
AsyncSoapCall(){
}
#Override
protected Integer doInBackground(Void... params) {
cd = new ConnectionDetector(getActivity().getApplicationContext());
// get Internet status
isInternetPresent = cd.isConnectingToInternet();
// check for Internet status
if (isInternetPresent) {
String namespace = getResources().getString(R.string.NAMESPACE);
String url = getResources().getString(R.string.URL);
String soapaction = getResources().getString(R.string.SOAP_ACTION);
String login = getResources().getString(R.string.login);
String mdp = getResources().getString(R.string.mdp);
isUrlAvailable = cd.isUrlAvailable();
// check for Internet status
if (isUrlAvailable) {
String idApplication = Installation.id(getActivity());
SOAPContact soapContact = new SOAPContact(namespace, url, soapaction, login, mdp);
soapContact.saveParams(getResources().getString(R.string.origine), db);
result = 1;
} else {
result = 2;
}
} else {
result = 3;
}
return result;
}
#Override
protected void onPostExecute(Integer result) {
super.onPostExecute(result);
}
#Override
protected void onPreExecute() {
Log.i(TAG, "onPreExecute");
}
#Override
protected void onProgressUpdate(Void... values) {
Log.i(TAG, "onProgressUpdate");
}
}
I don't get error my app crasha at this line:
Integer taskResult = task.execute().get();
try to get the value from onPostExecute like
#Override
protected void onPostExecute(Integer result) {
super.onPostExecute(result);
int yourNum = result;
}
that's it
Did you read the doc?
https://developer.android.com/reference/android/os/AsyncTask.html
AsyncTask has no "get" method.
You need to define a OnPostExecute method which will be called when your task is over with your Integer as a parameter.
public class MyActivity extends Activity
{
private Integer myInteger;
private void blabla(){
Simulation.AsyncSoapCall task = new Simulation.AsyncSoapCall() {
#Override
protected void onPostExecute(Integer result) {
//... Your code here ...
MyActivity.this.myInteger = result;
MyActivity.this.myMethod(result);
}
}
try {
task.execute();
} catch (Exception e) {
e.printStackTrace();
}
}
protected void myMethod(Integer integer){
}
}
Here is one method with the help of interfaces,
MainActivity.java
public class MainActivity extends AppCompatActivity {
static String TAG=MainActivity.class.getSimpleName();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
AsyncSoapCall request = new AsyncSoapCall(new AsyncSoapCall.AsyncSoapInterface() {
#Override
public void callBack(String callBackValue) {
Log.d(TAG,callBackValue);
}
});
request.execute();
}
}
AsyncSoapCall.java
public class AsyncSoapCall extends AsyncTask<Void,Void,Void> {
interface AsyncSoapInterface{
void callBack(String callBackValue);
}
AsyncSoapInterface callbackObj;
AsyncSoapCall(AsyncSoapInterface callbackObj)
{
callbackObj = callbackObj;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Void doInBackground(Void... params) {
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
callbackObj.callBack("Your value");
}
}
I have same stock item , I want to send local database to ApiService, But when I send also I want to update ProgressBar message. I tried the code below but it just shows when all proccessing is finishing.
ProgressDialog progress= new ProgressDialog(this);
progress.setTitle(getResources().getString(R.string.progress_exporting));
progress.setMessage("0/0");
when click button I call below method
public void Export() {
runOnUiThread(new Runnable() {
#Override
public void run() {
findViewById(R.id.btnExportOnlineWithStocktaking).setEnabled(false);
progress.show();
}
});
UpdateUI(send, total);
try {
switch (_stocktakingType) {
case Division: {
switch (_onlineExportType) {
case Item: {
isExport = ExportDivisionStocktakingItems(stocktakingId);
}
break;
}
} catch (Exception ex) {
}
}
// ExportDivisionStocktaking method
public boolean ExportCustomStocktakingItems(int stocktakingId) {
result = Boolean.parseBoolean(SendCustomStocktakingItems(stocktakingId,countResults).responseString);
}
My call back method
public ResponseModel SendCustomStocktakingItems(int selectedDivision, List<ExtensionServiceStocktakingItem> countResults) throws ExecutionException, InterruptedException {
return new SendCustomStocktakingItemsService(flag -> true).execute(String.valueOf(selectedDivision), countResults.toString()).get();
}
//AsyncTask method
public class SendDivisionStocktakingItemsService extends AsyncTask<String, Void, ResponseModel> {
public AsyncResponseSendDivisionStocktakingItems delegate = null;
public SendDivisionStocktakingItemsService(AsyncResponseSendDivisionStocktakingItems delegate) {
this.delegate = delegate;
}
#Override
protected ResponseModel doInBackground(String... parameters) {
RequestHandler requestHandler = new RequestHandler();
JSONObject params = new JSONObject();
try {
params.put("stocktakingItems", parameters[1]);
} catch (JSONException e) {
e.printStackTrace();
}
ResponseModel responseModel = requestHandler.getRequestPostString(UHFApplication.getInstance().apiUrl
+ "/api/MobileService/SendDivisionStocktakingItemsPost?stocktakingID="
+ parameters[0],
parameters[1]);
return responseModel;
}
#Override
protected void onPreExecute() {
UpdateUI(send,total);
super.onPreExecute();
}
#Override
protected void onPostExecute(ResponseModel responseModel) {
super.onPostExecute(responseModel);
if (HttpURLConnection.HTTP_OK == responseModel.httpStatus) {
delegate.processFinish(true);
} else {
delegate.processFinish(false);
}
}
}
//UICalled method
public void UpdateUI(int send, int total) {
runOnUiThread(() -> {
progress.setMessage(send + "/" + total);
Log.d("Send Data : ", send + "/" + total);
if (send == total) {
progress.dismiss();
Toast.makeText(getApplicationContext(), "Succsess", Toast.LENGTH_SHORT).show();
}
});
}
//Update
//Ok I have a simle example how can I use. Below code when I click button I wan to open progress firstly and after that for loop is working and update progres message. I try it but not working.
Firstly For loop is working and after that progres opened.
public void ExportTry(){
UpdateUI(send,total);
runOnUiThread(new Runnable() {
#Override
public void run() {
btnExport.setEnabled(false);
progress.show();
}
});
for(int i=0;i<1000000;i++){
UpdateUI(i,1000000);
}
}
You are missing the part of AsyncTask that will allow you to show progress messages while doInBackground is running. Take a look at onProgressUpdate and publishProgress on the same page.
publishProgress
void publishProgress (Progress... values)
This method can be invoked from doInBackground(Params...) to publish updates on the UI thread while the background computation is still running. Each call to this method will trigger the execution of onProgressUpdate(Progress...) on the UI thread. onProgressUpdate(Progress...) will not be called if the task has been canceled.
I'm using a very well IntentService to do some background tasks. In other parts of my app use only AsinkTasks for a short operation, but if I start the AsyncTask (after IntentService has finished its work), doInBackground and OnPostExecute are not called. Parts of my code:
IntentService:
public class MyService extends IntentService{
#Override
public void onCreate() {
super.onCreate();
...
...
}
#Override
protected void onHandleIntent(Intent intent) {
...
...
...
}
}
AsyncTask
private void caricaNomeAvatar() {
new AsyncTask<String, Void, String>() {
String nome = null;
String foto = null;
#Override
protected String doInBackground(String... urls) {
Log.d("doInBackground", "doInBackground");
nome = UT_drive_dropbox.AM.getNomeEcognome();
foto = UT_drive_dropbox.AM.getfoto();
return null;
}
#Override
public void onPostExecute(String result) {
Log.d("onPostExecute", "onPostExecute");
super.onPostExecute(result);
if (foto != null) {
new LoadAvatar(imgFoto).execute(foto);
} else {
finishAffinity();
Intent inte = new Intent(Drive_login.this, Menu_drawer_pro.class);
inte.putExtra("sync", true);
startActivity(inte);
}
}
}.execute();
}
call the method:
#Override
public void onConnOK() {
caricaNomeAvatar();
}
I want to catch exception of a thread in doInBackground and print the error message in onPostExcecute. The problem is I don't have the Throwable object in onPostExecute. How to catch Exception in non-UI thread and print the error message in UI-thread?
public class TestTask extends AsyncTask<Void, Void, List<String>> {
#Override
protected List<String> doInBackground(final Void... params) {
try {
...
return listOfString;
} catch(SomeCustomException e) {
...
return null;
}
}
#Override
protected void onPostExecute(final List<String> result) {
if(result == null) {
// print the error of the Throwable "e".
// The problem is I don't have the Throwable object here! So I can't check the type of exception.
}
}
}
Update after Arun's answer:
This is my AsyncTask wrapper class. It intends to do handling Exception in doInBackground but I can't find a good solution to do it.
public abstract class AbstractWorkerTask<Params, Progress, Result>
extends AsyncTask<Params, Progress, Result>
implements Workable {
protected OnPreExecuteListener onPreExecuteListener;
protected OnPostExecuteListener<Result> onPostExecuteListener;
protected ExceptionHappenedListener exceptionHappendedListener;
private boolean working;
#Override
protected void onPreExecute() {
if (onPreExecuteListener != null) {
onPreExecuteListener.onPreExecute();
}
working = true;
}
#Override
protected void onPostExecute(final Result result) {
working = false;
if(/* .........*/ ) {
exceptionHappendedListener.exceptionHappended(e);
}
if (onPostExecuteListener != null) {
onPostExecuteListener.onPostExecute(result);
}
}
#Override
public boolean isWorking() {
return working;
}
public void setOnPreExecuteListener(final OnPreExecuteListener onPreExecuteListener) {
this.onPreExecuteListener = onPreExecuteListener;
}
public void setOnPostExecuteListener(final OnPostExecuteListener<Result> onPostExecuteListener) {
this.onPostExecuteListener = onPostExecuteListener;
}
public void setExceptionHappendedListener(final ExceptionHappenedListener exceptionHappendedListener) {
this.exceptionHappendedListener = exceptionHappendedListener;
}
public interface OnPreExecuteListener {
void onPreExecute();
}
public interface OnPostExecuteListener<Result> {
void onPostExecute(final Result result);
}
public interface ExceptionHappenedListener {
void exceptionHappended(Exception e);
}
}
Change the return type of doInBackground() to Object and when you receive the result in onPostExecute(Object result) use the instanceOf operator to check if the returned result is an Exception or the List<String>.
Edit
Since the result can either be an Exception or else the proper List, you can use the following:
protected void onPostExecute(final Object result) {
working = false;
if(result instanceof SomeCustomException) {
exceptionHappendedListener.exceptionHappended(result);
}
else{
if (onPostExecuteListener != null) {
onPostExecuteListener.onPostExecute(result);
}
}
}
Also change the following statement:
public abstract class AbstractWorkerTask<Params, Progress, Object> extends AsyncTask<Params, Progress, Object>
Just store the Exception into a list and handle it later, as onPostExecute() is always called after doInBackground():
public class TestTask extends AsyncTask<Params, Progress, Result> {
List<Exception> exceptions = new ArrayList<Exception>();
#Override
protected Result doInBackground(Params... params) {
try {
...
} catch(SomeCustomException e) {
exceptions.add(e);
}
return result;
}
#Override
protected void onPostExecute(Result result) {
for (Exception e : exceptions) {
// Do whatever you want for the exception here
...
}
}
}
This is doable but rarely used, as in most situation, we want handle the exception as soon as it get thrown and catched:
public class TestTask extends AsyncTask<Params, Progress, Result> {
#Override
protected Result doInBackground(Params... params) {
try {
...
} catch(SomeCustomException e) {
// If you need update UI, simply do this:
runOnUiThread(new Runnable() {
public void run() {
// update your UI component here.
myTextView.setText("Exception!!!");
}
});
}
return result;
}
}
Hope this make sense.
Changing the return type of doInBackground to Object to possibly pass an Exception and then use instanceof() is a source of code smell (bad programming practice). It is always preferable to restrict your return type to the very specific thing you want returned.
Based on this answer simply add a private member to store the exception thrown in doInBackground and then check for it first thing in onPostExecute.
Only one Exception need be caught because you should stop the actions in doInBackground immediately once the exception is thrown and handle it gracefully in onPostExecute where you have access to the UI elements and so can inform the user of the mishap.
Generic example (body of the AsyncTask):
private Exception mException
#Override
protected Result doInBackground(Params... params) {
try {
// --- Do something --- //
}
catch( SomeException e ){ mException = e; return null; }
}
#Override
protected void onPostExecute(Result result) {
if (mException != null) {
// --- handle exception --- //
return;
}
// --- Perform normal post execution actions --- //
}