WindowManager$BadTokenException even when checking isFinishing() - android

Some people are getting this even tho I check if the activity is finishing or not. This app has a few million users and only 10 or so people are crashing. I am confused as to why.
private fun someFun(headerTitle: String, message: String) {
if (isFinishing) return
ComponentPopup.Builder(this)
.setTitleText(headerTitle)
.setMessageText(message)
.setPositiveButtonText("Some text")
.setNegativeButtonText("Some text")
.createPopup()
.show()
}
ComponentPopup is just a custom component that extends Dialog.
Crashlytics says I get this exception at .show(). I don't call this function on a background thread either. Only on onBackPressed().
What gives? Why do I get this exception even though I check isFinishing?
Tried to finish the activity manually. Still wasn't able to produce the problem.

I was getting the same exception. In my case the issue was I was passing the application context to the Builder instead of the Activity context. Hopefully, you are not doing so.
Just for testing, you may pass the context of your current Activity as YOUR_ACTIVITY.this instead of this.
This Issue happens when the user leave the activity before the diloag shown. So the dilaog didn't get the window of the specified Actvity to be show on.
You can generate the crash by calling the show of dialog and then instantly leave the activity.

Related

unable to make toast in activity constructor

I am getting an error as Null pointer exception and unable to instantiate activity when I am creating a toast in activity constructor.I want to know the reason why toasts are working in onCreate method but not in activity constructor
The OS is responsible for constructing your Activity classes. This is because it needs to perform some setup, including providing the Activity a proper base Context. Without this, you cannot make Toasts.
In general, you should avoid doing anything in the constructor of an Activity (and you should definitely not be making instances of them yourself using new).
Usually a Toast appears as a feedback to user input (say a button click) or when some external event is registerd (say a network error happend or new incoming data is available).
However, to me it sounds as though you want to show a Toast right after opening your activity, is that correct? Then you should put it in the onCreate method of your activity. An example Toast is made like this
Toast.makeText(MainActivity.this, "Hello World", Toast.LENGTH_LONG).show();
You might also consider putting this call in the onResume method. I recommend getting familiar with activity lifecycles.
Instead of using Toasts you might also want to check out Snackbars.

Activity has leaked window?

I am having one java class in that class as soon some one purchases our application then it will start downloading and progress dialog has to appear instead it goes to some other page and when i come out of the application and when i restart then it starts downloading.
Please Help me out from this mess...
Thank you
Check the condition for dialog, before showing.
Like this
if(pDialog!=null)
{
if(!pDialog.isShowing())
{
pDialog.show();
}
}
and also while removing the dialog in onPostexecute() check for null.
if Still not works just remove the pDialog and try once with your code.
Two causes for your error happen:
The error will happen if you're trying to show a Dialog after you've exited an Activity.
Also, if an unhandled Exception was thrown in your AsyncTask, which would cause the Activity to shutdown, then an open progress dialog will cause the Exception.
According to the Log you've posted, the error happens after you call pDialog.show() which might be the 1st cause I've mentioned before.
Also you are calling finish() in many parts of your code, maybe one of these calls are making your Activity to stop and leaking your Dialog.
You must check which one of them is finishing your Activity before you show the Dialog. A good solution is to dismiss the Dialog (if it's showing) before calling finish().

Undefined result when opening managed dialog in AsyncTask when in background

I have a problem that causes me some problems when a user (or another app, like the phone-application) pushes my application to the background.
My application does following:
A User can enter some information that is supposed to be pushed to a server.
When the user clicks "Send" i open a managed ProgressDialog and start an AsyncTask that performs the server communication.
When server communication is complete the AsyncTask reports back to my Activity where i perform a dismissDialog().
Directly after dismissDialog(), I will show another managed dialog using showDialog() that will inform the user about whether the submission was ok or if it failed.
This all works perfectly without any issues; however, when a call happens to come while the AsyncTask is running I get (seemingly random) one of these results:
The activity holding the managed dialog is dismissed completely and the previous view from the stack is presented when I come back.
The activity holding the managed dialog is still on screen, but it is grayed out without showing a dialog. The only way to fix this is to rotate the phone at which point it shows the "Submission sent"-dialog exactly the way it should and everything is ok after that.
All this happens without any warning messages so I get absolutely no clues as to why Android is behaving this way.
I know a way around this and that is to cancel the AsyncTask (so no dialogs are shown at the end). However, in this very use-case the requirements are that the app has to try to complete the server transaction so that there is as little confusion as possible (i.e. the user wondering if it was really sent or not).
Has anybody else had this issue and knows a way around?
I see recommendations to hold a reference to the asynch task in onRetainNonConfigurationInstance
What to do with AsyncTask in onPause()?
Or implement a bus:
https://github.com/commonsguy/cwac-bus/tree
EDIT: The complexity of your challenge is two fold:
1) saving and restoring state of your app on a kill such as when there is an incoming phone call
https://sites.google.com/site/jalcomputing/home/mac-osx-android-programming-tutorial/saving-instance-state
2) somehow continuing the asyncTask on kill instead of canceling it onPause
https://sites.google.com/site/jalcomputing/home/mac-osx-android-programming-tutorial/asynch
Both of these are significant challenges alone, and trying to fix both at the same time would give me a headache. In fact, I am getting a headache just thinking on it :) One clue is that you say the dialog returns on orientation change. This MAY be due to the fact that using the standard architecture for dialogs, the OS handles saving and restoring the state of dialogs for you on orientation change.
[EDIT] See CommonsWare
#Override
public Object onRetainNonConfigurationInstance() {
task.detach();
return(task);
}
and
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
bar=(ProgressBar)findViewById(R.id.progress);
task=(RotationAwareTask)getLastNonConfigurationInstance();
if (task==null) {
task=new RotationAwareTask(this);
task.execute();
}
else {
task.attach(this);
updateProgress(task.getProgress());
if (task.getProgress()>=100) {
markAsDone();
}
}
}
where task is an instance of
static class RotationAwareTask extends AsyncTask<Void, Void, Void> {
I see no reason why this would not work for all types of soft kills, but on a hard kill, well, you get killed. Dead is dead :)
Without looking at your code it is slightly difficult to say what the problem is. However, here is something you could use to help get around the problem. You can override the onPause() method of your Activity.
This is taken directly from the Android Acitivy javadoc:
onPause() is where you deal with the user leaving your activity. Most importantly, any changes made by the user should at this point be committed (usually to the ContentProvider holding the data)

Android: Activity closing when in dialog

I have a strange situation I am seeing.
I am reading some info from a database , then bringing up a dialog :
PSEUDO
val = DBaseManager.readValue(i,POS_ONE);
if(val == 1)
{
Dialog_Test myDialog = new
Dialog_Test (myContext,"",new addListener(),DBaseManager);
myDialog.show();
}
as you can see I pass into the Dialog the DBaseManager so it can use it also.
then in there I use it like this :
DBaseManager.readValue(k,POS_TWO);
etc.
Now this works 99% of the time, however I have had some crash logs pointing to these lines in the dialog with null pointer exceptions.
To me this is indicating that on some devices my onPause or OnDestory methods are being called in the main activity which closes and nulls DBaseManager. These are 1.6, 2.2 and 2.3 devices.
So the question is why , and how to prevent ? I have added some null pointer checks in to prevent the crashes but it still far from ideal.
UPDATE: On my devices at least when I do a screen rotate the activity is restarted and the dialog disappears - could it be on some the dialogs remains up???
This probably depends on the scope of your Dialog and where in the code you are opening it. The default behavior is for the Activity to go through its lifecycle when the orientation changes unless you explicitly handle orientation changes and override onOrientationChanged. You might want to do something like maintain the state of your dialog at the Activity level (such as adding a boolean isDialogDisplayed as a class variable) and then in onCreate or onResume check that and reopen the dialog.
As far as the DBaseManager object being cleaned up, I have experienced similar things. Large objects getting cleaned up when you don't expect them to (there are still pointers to these objects, but they've been nulled by the system somehow). I've identified these in my applications and just been more careful. Instead of null checking and reloading when null only when it's possible that your code could have nulled the variable (or using lazy loading), I'd always treat this object as if it were lazy loaded. Add a method that returns this object instead of accessing it directly, and always check for null and reload if it is.
For both of these two issues, you might want to override all the lifecycle methods of this Activity and log them. Don't forget to call the lifecycle methods on the base class within your overrides (ie. public void onPause() { super.onPause() ..., etc)!

nested AlertDialogs in android

I'm trying to display an AlertDialog inside of another AlertDialog. When the user clicks on the any item within the initial AlertDialog another AlertDialog is created and shown.
I'm following the correct pattern for creating and displaying AlertDialogs, the problem is as soon as the code reaches the point where the innerDialog.show() method is encountered the application fails. The logcat prints an uncaught runtime exception:
android.view.WindowManager$BadTokenException : Unable to add window -- token null is not for an applicaion
I'm wondering if i'm allowed to call the show() method on the innerAlertDialog manually.
The outer AlertDialog is working because i'm using the callback onCreateDialog() method.
In previous versions there was a bug where getApplicationContext() returned null.
I still dont quite if it has been fixed however with dialogs, its always better to send this.
And for the main question, its working as designed to avoid locking the UI thread.
I have seen people recommending creating a new layout with the theme of the dialog and start the activity on the first dialog, however I havent try this yet.

Categories

Resources