I have a really weird problem, which I am unable to debug so far...
Thing is...my app needs to download something to work. So in the beginning of the onCreate() method, I check if that something is already downloaded. If not, I pop a dialog up asking the user to download it.
if (!isInstalled) {
showDialog(DIALOG_INSTALL);
} else {
start();
}
Where start() method performs some other action. Now, that showDialog calls this:
builder = new AlertDialog.Builder(MyApp.this);
builder.setMessage("Would you like to install...")
.setCancelable(false)
.setPositiveButton("Install", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.dismiss();
aManager.install(MyApp.this);
}
});
dialog = builder.create();
return dialog;
My dialog is shown and I am clicking, so aManager.install() is called. I am passing the context because that aManager.install() pops up a ProgressDialog to show downloading progress and spawns a new thread in which everything is downloaded. So obviously before creating my dialog I make a Handler to receive the response from that aManager.install(). And the response MAY vary, because for example the internet connection isn't available (Exception raised and catched and listener called with different code).
Now, when that happens (Exception) I would like to call another dialog saying "something went wrong, would you like to retry?"...so another call to showDialog(DIALOG_REINSTALL) (this time with another code).
Thing is...the showDialog() gets called (I can verify this by logging) but the dialogs doesn't show up. Instead my application JUST HANGS!?!?!?
Does someone have a clue why it's doing this???? No exception raised, absolutely nothing from logcat, I can't tell WHERE it's hanging...just see that the method is called and the dialog should be displayed...
Thank you very much!!
Looks like you have a deadlock. I would put the download code on the separate thread e.g. use AsyncTask. In task.onPreExecute() you can dismiss 1st dialog and pop-up your progress dialog which you update by overwriting task.onProgressUpdate()
Use .show() instead of .create().
Related
I’m getting really confused with dialog boxes in Android and need some advice.
Everything was initially going well. I had numerous dialogs being created within MainActivity opened via a Navi Drawer. The dialogs where created very simply using code like this:
private void exportDialog() {
LayoutInflater inflater = this.getLayoutInflater();
final View formElementsView = inflater.inflate(R.layout.export_data, null, false);
AlertDialog msgBox = new AlertDialog.Builder(this)
.setView(formElementsView).setTitle("Export Responses")
.setIcon(android.R.drawable.ic_menu_share)
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// Code...
}
})
.create();
msgBox.show();
}
But I started to notice problems when the device resumed from lock screen. Switching/pausing/resuming worked fine, but the locked screen seemed to kill the activity context and when the app resumed the dialogs became graphically corrupt and I got the “Activity has leaked window” error message in the logs.
So, I started again. I moved all the dialogs into DialogFragment classes which seems to be the ‘proper’ way to do it. This removes the error and graphical glitches. Great!
But I can’t work out how to add more than one dialog listener to MainActivity. So I’ve got:
public class MainActivity extends Activity implements LogInDialog.NoticeDialogListener{
but can I add more?
Until I work out how to do this, I’ve altered many of the MainActivity methods and moved them into the relevant dialog classes, which works fine but seems a rather linear approach. It would be nice if MainActivity could act upon each dialog response.
As you can guess, I’m not a professional developer so I’m getting rather lost!
UPDATE:
OK, it seems the original problem of graphic glitches and "leaked window" messages was because the dialog boxes were not being dismissed correctly. Adding the following seems to have greatly improved matters:
#Override
public void onDestroy() {
super.onDestroy();
if (DialogBox1!=null){
DialogBox1.dismiss();
}
DialogBox1= null;
if (DialogBox2!=null){
DialogBox2.dismiss();
}
DialogBox2= null;
if (DialogBox3!=null){
DialogBox3.dismiss();
}
DialogBox3= null;
...
use inner classes that implements LogInDialog.NoticeDialogListener
I'm trying to figure out if the map is loaded before I open a dialog on the MainActivity (with map fragment) it would be helpful if there was a
if(map.isLoaded()){
//show dialog
}
if I just normally open a dialog after the map is already loaded, then it opens fine, but I'm switching activities and I wanted the dialog to open as soon as the activity starts but it seems as if the dialog is beating the loading map, then through the process of it loading, the dialog goes away and the map comes up. I've seen things about javascript and theres something regarding tilesLoaded() but I'm not seeing anything like that either. Any suggestions??
How about GoogleMap.OnMapLoadedCallback?
private GoogleMap mMap;
mMap.setOnMapLoadedCallback(new GoogleMap.OnMapLoadedCallback() {
public void onMapLoaded() {
//do stuff here
}
});
Here is my method, it works fine and shows the Dialog.
public void showDialog(){
final Dialog dialog = new Dialog(this);
dialog.setContentView(R.layout.mylayout);
dialog.show();
}
I have a test project and I would like to test that the Dialog is showing up. I would like to apply the .isShowing() method. Something like this...
assertTrue(dialog.isShowing());
But I don't know how to get to the dialog variable within my test.
I am not using Robotium (this isn't an option for me).
I'm currently using the ActivityUnitTestCase to test with. If any more information is required please don't hesitate to ask.
EDIT
I have attempted to use the answer below by making the Dialog public
public Dialog getDiag(){
return dialog;
}
Using this answer: I have a new problem when I run showDialog() in the test, it breaks when it hits: dialog.show();
android.view.WindowManager$BadTokenException: * Unable to add window -- token null
Declare Dialog outside showDialog function and then implement a method which returns this Dialog instance.
public Dialog getDiag(){
return dialog;
}
and then do something like this
assertTrue(new YourClassName().getDialog().isShowing());
I'm begining with Android development. I have an asynchronous operation, but my intention is wait the operation is completed, and after that, continue the execution of my program.
I have used AsyncTask, and all its methods, but I got error, because on the onPreExecute method I want to show another Activity, so I guess I can't show another Activity. That's the reason I want to wait to complete the asynchronous operation.
Greetings
1st edit:
I've used AsyncTask(onPreExecute, doInBa..., onPost... ), but none method works. I understand how it works the AsyncTask class, but I want stop the execution when I invoke one asynchronous thirdparty method, because in the listener that needs, I change the value of a String variable X, and after invoke my method, that uses the thirdparty method, I use the variable X. I got an exeption because the variable hasn't updated.
Please, read and follow example of AsynTask. You need to override onPostExecute
Not entirley sure what the question is but AsynTask has a method that you can call after everything has completed. A good practice is to have a dialog or a spinner showing that work is happening then dismiss it.
class loadingTask extends AsyncTask<String, Void, String> {
protected String doInBackground(String... urls) {
//Do work
}
protected void onPostExecute(String s) {
ShowProgress.dismiss();
Intent myIntent = new Intent(this, PostExAct.class);
startActivity(myIntent);
}
}
In your on create:
ShowProgress = ProgressDialog.show(MainActivity.this, "",
"Loading. Please wait...", true);
new loadingTask().execute("params here");
This will show a loading dialog and while the work is being done then will be dismissed when the work is finished.
I am trying to write some Activity tests for an app, and one particular scenario that I want to test is that when I click a certain button, the Activity view updates accordingly. However, clicking the button causes a somewhat long running asynchronous task to start and only after that task is completed does the view change.
How can I test this? I'm currently trying to use the ActivityInstrumentationTestCase2 class to accomplish this, but am having trouble figuring out how to have the test 'wait' until the asynchronous part of the button click task is complete and the view updates.
The most common and simplest solution is to use Thread.sleep():
public void testFoo() {
TextView textView = (TextView) myActivity.findViewById(com.company.app.R.id.text);
assertEquals("text should be empty", "", textView.getText());
// simulate a button click, which start an AsyncTask and update TextView when done.
final Button button = (Button) myActivity.findViewById(com.company.app.R.id.refresh);
myActivity.runOnUiThread(new Runnable() {
public void run() {
button.performClick();
}
});
// assume AsyncTask will be finished in 6 seconds.
try {
Thread.sleep(6000);
} catch (InterruptedException e) {
e.printStackTrace();
}
assertEquals("text should be refreshed", "refreshed", textView.getText());
}
Hope this helps.
If you're using Eclipse, you could use the debugger by setting a breakpoint in the code that updates the view. You could also set some breakpoints in the long running task to watch and ensure that all your code is executing.
An alternative, write some log or console outputs in your long-running task and the view updater code, so you can see the progress without interrupting the thread by a debugger.
As a piece of advise, if its a long-running process, you should be showing a progress bar of some description to the user, so they aren't stuck there thinking "Is something happening?". If you use a progress bar with a maximum value, you can update it in your long-running task as it is running, so the user can see the activity going from 10% to 20%... etc.
Sorry if you were expecting some kind of jUnit-specific answer.
I ended up solving this by using the Robotium library's Solo.waitForText method that takes a string and timeout period and blocks until either the expected text appears or the timeout occurs. Great UI testing library.