Check if AsyncTask is taking too long - android

I have an AsyncTask that get info from the web. Sometimes the connection fails and the AsyncTask processdialog is running forever.
In the doInBackground I have a check in the end if my catched info are empty and if this is the case, it should appear Positive button/Negative button, but this is not happening. The dialog is just running.
How can I check if an AsyncTask is taking too long time (Maybe 5 seconds) and dismiss the dialog?
Code snippet (doInBackground):
//orders is my ArrayList<Order> object, from my own Order class.
if(orders==null) {
pdia.dismiss();
AlertDialog.Builder alt_bld = new AlertDialog.Builder(ctx);
alt_bld.setMessage("Try agin?")
.setCancelable(false)
.setPositiveButton("Try again", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
button_refresh.setVisibility(View.GONE);
new ListTask().execute(null, null , null);
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
AlertDialog alert = alt_bld.create();
alert.setTitle("Connection failed!");
alert.show();
}
else {
return orders;
}
Thanks in advance and tell me if you need more info!

Instead of checking your result in doInBackground() you can get the value from the process and check it in onPostExecute(), like this:
protected void onPostExecute(ArrayList<Order> localOrders){
super.onPostExecute(localOrders);
if (localOrders==null) {
// Paste the positive and negative DialogListeners here
// and dismiss the dialog.
}
}
The result from your doInBackground() process passes into onPostExecute's parameter, thence you can check if your ArrayList object is empty or not.

But then writing the above code snippet in the onPostExecute will defeat the purpose right? We want the user to not wait past 5 seconds for an answer from the webservice and therefore we must handle the timeout within doInBackground itself.

Related

alert dialog written in non activity class not showing alert dialog when dismissed from calling activity

I crate a class called "Dailog" for building alert dialog which has its own dismiss() method to dismiss the dialog. and then use it's Object in many screens where I need to show alert dialog.
In my calling Activity class I create instance of Dailog class, and then call up method which does some network operation(which is not async task) and then when network task is finished I dismis the dialog object. I need wait on the same screen untill networks operation finishes but with dialog showing something is happening.
While debugging I do see that that dialog object is not null. No exception throughout this execution but alert dialog never shows up
public class Dialog {
private AlertDialog dialog ;
private AlertDialog.Builder builder;
public Dialog(Activity activity , String Message , String titleMsg) {
builder = new AlertDialog.Builder(activity);
builder.setMessage(Message);
builder.setTitle(titleMsg);
builder.setCancelable(false);
builder.setIcon(R.drawable.logoxl);
dialog = builder.create();
dialog.show();
}
public void dismiss(){
this.dialog.dismiss();
}
}
// my activity method(openMenu) on button click where I am calling this
public void OpenMenu(View view){
Dialog progress = new Dialog(this , "We are fetching today's menu...Please Wait" , "Biji's Kitchen");
try {
Data fetcheddata = new Data(this);
fetcheddata.getMenu();
}catch(Exception e){
e.printStackTrace();
}
progress.dismiss();
}
Data.getMenu() is network operation and should be executed in the separate thread. Dialog.dismiss(), on the other hand, is UI operation and should be executed in main thread.
So, in Data thread you should wait for network request completion and then post message to UI thread to dismiss the dialog after that.
P.S. To be more clear: your current implementation does show dialog - and immediately dismisses it as show and dismiss are called one after another in UI thread but data is still loading in another thread.
Try commenting this Line. I hope it should work.
//progress.dismiss();

IdlingResource not waiting in AndroidTests

I am trying to test MyActivity shows an alert dialog when incorrect intent extras were passed. It is a url, so I pass the url to a internal webView to load the url and show an alert if any error happened. The alert should be dismissed when the positive button is clicked.
This is how the alertDialog is created when the error happens
// Method in `MyActivity.java` called when the url couldn't be loaded
private void showAlertDialog(final String title, final String message) {
final MyActivity self = this;
runOnUiThread(new Runnable() {
#Override
public void run() {
if (!isFinishing()) {
alertDialog = new AlertDialog.Builder(MyActivity.this)
.setTitle(title)
.setMessage(message)
.setCancelable(false)
.setPositiveButton(BUTTON_OK_TITLE, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
self.alertDialog = null;
//self.finishWithMessage(messageRaw, true);
}
}).create();
alertDialog.show();
}
}
});
}
In the test, I am using ElapsedTimeIdlingResource taken from chiuki's answer to wait 10 seconds after launching the activity and assert the alertDialog was created and showing.
Then I am pressing the alert button and wait again 10 seconds to try to assert it is gone.
This is the test code MyActivityTest.java:
#RunWith(AndroidJUnit4.class)
public class MyActivityTest {
#Rule
public ActivityTestRule<MyActivityTest> mActivityRule = new ActivityTestRule<>(MyActivityTest.class, true, false);
#Test
public void testErrorDialog() {
Intent intent = createIntentWithWrongExtras();
mActivityRule.launchActivity(intent);
// Wait
IdlingResource idlingResource1 = new ElapsedTimeIdlingResource(10000);
Espresso.registerIdlingResources(idlingResource1);
assertNotNull("Activity should have been created", mActivityRule.getActivity());
assertNotNull("AlertDialog should have been created", mActivityRule.getActivity().alertDialog);
assertTrue("AlertDialog should be showing", mActivityRule.getActivity().alertDialog.isShowing());
// Test clicking the button dismisses the alert
mActivityRule.getActivity().runOnUiThread(() ->
mActivityRule.getActivity().alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).performClick()
);
IdlingResource idlingResource2 = new ElapsedTimeIdlingResource(10000);
Espresso.registerIdlingResources(idlingResource2);
assertTrue("AlertDialog should NOT be showing", mActivityRule.getActivity().alertDialog == null || !mActivityRule.getActivity().alertDialog.isShowing());
Espresso.unregisterIdlingResources(idlingResource2);
}
}
However the test always fails:
"AlertDialog should NOT be showing"
I don't think I am understanding well what is really going on. I wrote some logs and I can see that idlingResource1 never waits for 10 seconds. Also I know alertDialog becomes null when dismissed but that happens after the last assert, so idlingResource2 is not working either? Why? Is this the right way to test this?
IdlingResources make Espresso wait. But you do not use Espresso to test (besides registering IdlingResources that have no effect), so the test runs straight though without waiting and your test fails.
If you replace your IdlingResources with simple Thread.sleep() your test should work. At least it would wait.
Read a little bit about Espresso, it's easy and would really improve your test: https://developer.android.com/training/testing/ui-testing/espresso-testing.html
I don't think you are using Espresso in the right way.
Try remove the idlingResources, and replace the first three assertion with something like:
onView(use_matcher_to_match_the_dialog).check(matches(isDisplayed()));
Espresso will wait until UI thread to become idle.
Then, do the click in Espresso way:
onView(use_matcher_to_match_the_button).perform(click());
and the final assertion:
onView(use_matcher_to_match_the_dialog).check(matches(not(isDisplayed())));

Handle with AlertDialog into the doInBackground

I am trying to call AlertDialog into AsyncTask. I wrote this code and it works, but when I choose item in the AlertDialog and then call uiHandler.getLooper().quit(); to continue code proccesing, AlertDialog is freezes (doesnt closing, staying until activity finishes) but backgroundUI continue proccesing. I think it's because AlertDialog has no time to perform dismiss() method before infinity loop is ending. Please, help me to solve this problem. I need to do this only in doInBackground method.
#Override
protected Void doInBackground(Void... arg0) {
Looper.prepare();
final Handler uiHandler = new Handler();
uiHandler.post(new Runnable() {
public void run() {
AlertDialog.Builder chooser = new AlertDialog.Builder(ctx);
facultyChooser.setTitle("Choose")
.setCancelable(false)
.setItems(faculties, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int item) {
uiHandler.getLooper().quit();
}
})
.create()
.show();
}
});
Looper.loop();
}
PS: It's not full code for easier reading.
You have to run you alert before the doInBackground (onPreExecute) and dismiss your dialog after it (onPostExecute)
Technically, It is not passible to do UI related task in doInBackground() method on Asyntask. You have to use onPostExecute()/onPreExecute() of Asyntask for showing AlertDialog.

Android - displaying alert dialog during doinbackground while catching exception

I have this code and it goes to catch as soon as it hits Source.httpConn and it sends the exception down below to catch.
try
{
JSONTokener sbTokener = new JSONTokener(Source.httpConn(infoUrlStr, Main.this).toString());
//array için hazırlandı
JSONArray jArray=new JSONArray(sbTokener);
//arraye eklendi
for(int i=0; i<(jArray.length()); i++)
.
.
.
}
Down in the catch part there is my alert dialog method. It normally works pretty well but I suspect that I have the problem because of the doInBackground. The application crashes before displaying the below alert dialog. All the try-catch is in my doInBackground method in ASyncTask.
catch (Exception e) {
AlertDialogDisp(Main.this, noServ, noServLog);
}
How can I make my application NOT crash and just display this alert dialog and then return to my Main activity as it was. Here is my alert dialog method:
protected void AlertDialogDisp(Context dialogContext, String head, String log) {
new AlertDialog.Builder(dialogContext)
.setTitle(head)
.setMessage(log)
.setPositiveButton("okay", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// On Alert Dialog Button
dialog.dismiss();
}
})
.show();
}
You cannot update ui from doInbackground. doInbackground is invoked on a backgroudn thread. Ui should be updated on the ui thread. Return result in doInbackground and update ui in onPostExecute
For more info check the docs
http://developer.android.com/reference/android/os/AsyncTask.html
You can also use runOnUithread which is a method of activity class
runOnUiThread(new Runnable(){
public void run() {
// dispaly dialog here
// no network related operation here
}
});
Show your dialog in runOnUiThead which is a method of activity class.
runOnUiThread(new Runnable(){
public void run() {
//write your alert dialog code here
}
});

Android AsyncTask Dialog Alert

I have a splash screen which check an URL if there's any new content on the server. If show i wish to show a AlertDialog, to the app user so that depending on the action of user,i.e if YES download new contents from the server and get it to database else if NO load the contents for the app from the server.
However i am not being able to use an alert dialog inside AsyncTask
My snippet code is as:
protected String doInBackground(String... mode){
/* I AM QUERY MY DATABASE FOR THE PREVIOUS CONTENT(SAY CONTENT 1, CONTENT 2);
* then i start my connection to the server which has an xml file with the content
* info (say content 3), at this stage .
* i Check certain condition here,
* say if result ==0 then i wish to display an alertdialog.
* I used an alert dialog and i get some error. Stating use Looper or Handler.
* Can anyone help me with this?
*/
}
Edited
So in
doInBackGround(String... mode){
if(result==0){
// how do i implement this alert show that if the dialog appears and on clicking Yes i wish to exectute the URL handling part below
AlertDialog.Builder alert = new AlertDialog.Builder(context);
alert.setTitle("Updates Found");
alert.setMessage( "New Updates for has been found.\n Would you like to download ?\n"
+ "Whats the update: Checking "+pld.result.get(i).get( "issue" ));
alert.setIcon(android.R.drawable.ic_dialog_info);
alert.setPositiveButton(android.R.string.yes,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
try {
URL url = new URL(pld.result.get(i).get("link"));
ManageZipFile.getArchive(url,pld.result.get(i).get("issue"), file);
}
catch (Exception ex) {
Log.d(TAG, "Exception from URL"+ ex.getMessage());
}
progressState += updateProgressBar(20);
pld.saveCoverData(pld.result.get(i).get("issue"));
try {
pldContent = new PullLoadData(getString(R.string.files_path)
+ pld.result.get(i).get("issue")
+ "/contents.xml",context);
pldContent.getNewsItems();
progressState += updateProgressBar(20);
}
catch(XmlPullParserException e) {
Log.e(TAG, "GetNEWSITEM "+ e.getMessage());
}
catch (IOException e) {
Log.e(TAG, "XML FIle not found" + e.getMessage());
}
}
});
alert.setNegativeButton(android.R.string.no,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int arg1) {
dialog.dismiss();
}
});
AlertDialog showAlert = alert.create();
showAlert.show();
}
}
This is because the method doInBackground runs on a non-UI thread, and an AlertDialog needs to be displayed on the UI-thread.
To solve your problem, move the code for your AlertDialog to the method onProgressUpdate in AsyncTask, then when you want to display the Dialog call publishProgress() from doInBackground
protected String doInBackground( String... mode ) {
if( something )
//Conditions for showing a Dialog has been met
}
protected void onProgressUpdate( Void... params ) {
//Show your dialog.
}
If you need to pass some kind of variable/data to the dialog, you can pass the kind of data you declared in extends AsyncTask<Params, Progress, Result> - where Progress is the type of parameter you can pass via the publishProgress( myVariable )-method.
UI thread means it is associated directly with your UI.you cant do operations like network datafetch,disk access etc which require large processing time in your UI thread. They should be done in seperate thread.
AsyncTask helps to carry out theese operations in seperate thread which may otherwise results in infamous ANR error.(application not responding).
AsyncTask contain methods like onPreExecute() onPostExecute() onProgressUpdate() ,doInBackground ()etc you can access UI thread from onPreExecute() onPostExecute() onProgressUpdate() .The operation requiring longer processing time should be carried out in doinbackground().
I can't understand the functionality demands from your question but if you want to display Alert Dialog before data fetching operation,Display it from onPreExecute()
or if you want to display after data fetch Do it from onPostExecute().

Categories

Resources