IllegalArgumentException when dismissing dialog in async task - android

My Problem is similar to this one:
Error on dismissing ProgressDialog in AsyncTask
I have an AsyncTask that creates a dialog in onPreExecute like this:
dialog = ProgressDialog.show(activity, "login", "logging in, one moment please");
And dismisses the dialog in onPostExecute like this:
if (dialog != null && dialog.isShowing()) {
dialog.dismiss();
}
Still, i get error reports from users on the line where i do diolog.dismiss() with the message:
java.lang.IllegalArgumentException: View not attached to window manager
The most common root-cause is - or so i've read - when a user switches orientation (from portrait to landscape or vice versa).
My app however is forced to portrait mode, so this can not be the cause. (i've double checked this to make sure it really is not possible)
The reporter of the before mentioned post solved it in the end (and i've read this solution elsewhere too) by creating an inner class for the AsyncTask in the activity class and working with onCreateDialog from the activity class and calling showDialog from the AsyncTask. (read his post if you don't understand this)
I've begun trying to implement that, but it seems that showDialog is deprected: so this is not a solution for me.
The last solution i've found is by simply catching the Exception. I had thought of that myself too, but only as a last resort. I prefer to understand what really goes wrong and anticipate on that instead of simply catching the exception and not knowing what is going on.

You should add this in the manifest.xml
upto API level 12
<activity
android:label="#string/app_name"
android:name=".Activity_calling_AsyncTask"
android:configChanges="keyboardHidden|orientation">
after apl level 12,
<activity
android:label="#string/app_name"
android:name=".Activity_calling_AsyncTask"
android:configChanges="keyboardHidden|orientation|screensize">
</activity>
hope this will help you.

If what Chad is saying is correct - that some devices might start in landscape for a fraction of a second - then i think this is the most likely cause for getting the error-reports. While the solution of Rajendra might be able to prevent that, i've decided it really does feel like applying a band-aid as others have pointed out, since screen-rotation is not the only source of the real problem.
After some more searching, i've found two solutions:
Implementing the AsyncTask as part of a class which inherits from Application class, which is explained here: Handle screen orientation changes when there are AsyncTasks running
Implement onRetainNonConfigurationInstance() / setRetainInstance(). An example of the first is given here: http://twigstechtips.blogspot.com/2011/11/for-my-app-moustachify-everything-i-was.html - however, the method itself is deprecated, so it would be better to use setRetainInstance in a similar fashion.
And just for completeness, there's also the Droid-Fu for Android library, which claims to be able to solve this problem.

Related

Why is a portion of the screen not been covered by the default transparency of the DialogFragment?

After trying to solve a memory leak issue with the InputMethodManager caused by the keyboard when triggered from a DialogFragment. and other related issues with the imputMethodManager + Dialogs + configurationChanges, which included changes to the manifest like:
android:windowSoftInputMode="adjustPan"
android:windowSoftInputMode="adjustPan|stateUnchanged"
Plus various overrides to onStart(), onStop(), onDestroy() inside Dialog's LifeCycle. Overrides to onDestroy() and onCreate() on Activity.
GlobalLayoutListener's and GlobalFocusChangeListener's with Handlers where also tested.
Changes that for the most part (all of them) have already been discarded as they did not worked.
A portion of the screen began to appear not covered by the default transparency of the DialogFragment on ALL dialog Fragments of the project which include: DialogFragment.class, AppCompatDialogFragment.class and normal AlertDialog.Builder()
I tried to roll back all changes, which at the end, ended up being a single line in FragmentActivity:
#Override
protected void onDestroy() {
super.onDestroy();
ViewToolUtils.fixInputMethod(this);
}
Which uses reflection to access the leaking field.
Field declaredField = inputMethodManager.getClass().getDeclaredField("mCurRootView");
if (declaredField == null) continue;
if (!declaredField.isAccessible()) {
declaredField.setAccessible(true);
}
Object obj = declaredField.get(inputMethodManager);
...
declaredField.set(inputMethodManager, null);
, but the uncovered portion of the screen still persists.
Sadly the last version on git was committed before the past week which was dedicated to fix some memory leak issues that were thought to be easily fixable but ended up transforming in some heavy overhauls, so I don't think that's an option...
The changes where first applied on a Samsung j7 Pro, and the dialogs are working with complete normalcy.
But when the changes where tested on a Samsung J5 the project never went back to normal on that device, even when all the changes were rolled back, with caches being invalidated and restarted.
Both devices have been part of this process and the first sign of this issue appeared after this particular fix was applied.
The very suspicious thing about this is that the white uncovered part actually resembles the keyboard... even though is smaller by some millimeters.
I don't mind If I could FORCE the opacity all the way down or DISABLE it entirely, at this point I don't care..., I am kinda desperate tbh.
It seems like this maybe a API level problem I know 4.4.4 - 6.0 all have weird and inconsistent UI oddities. Although you said you reverted it there may be something very small, "unrelated", seemingly benign configuration change.
In the mean time since you are open for work arounds this might help you. DialogFragment with clear background (not dimmed) You could manually set the window to dim and that might override whatever is causing it. If that doesn't work you can set the window to not dim at all and then you can't tell the difference. You could even restrict this to Samsung J5 API level.
Well, the solution was forgetting about everything, taking a bath, some pills and going to sleep.
Also some important tips:
Optimizing Imports to clear any extra imports.
".txt" everything that is not needed.
Comment everything that's not needed.
Clearing AS caches + restart,
Uninstalling everything from all devices.
Clearing the testing DB (Just in case).
Rebooting all devices.
That seemed to be the solution.

Can somebody clarify it this is a leak?

Please I would like to understand this situation.
If I rotate my Android application a few times and I look into the memory dump I find more than one instance of my Activity.
That looks like a leak.
But if I force garbage collection just before getting the memory dump (by pressing the button in android Studio) I find only one instance of my Activity.
I am very inclined to think I don't have a leak.
Please does anybody have a definitive answer?
Shouldn't helped you the parameters added to your Activity like:
android:configChanges="keyboardHidden|orientation"
After that, you could handle logic of orientation changes by yourself in the onConfigurationChanged method.
Or the second solution (couldn't completely imagine the structure of your project) should be using the launchMode parameter in AndroidManifest.xml

Android: Execute code when app is "activated", not on orientation change

in my application (minSdkVersion 17, but I am flexible concerning this), I have a single activity. It displays some kind of timetable. I want to let it show the current day and scroll to the correct time.
This functionality is already working perfectly fine.
I want to do this everytime when the app is started, or everytime when the app becomes active again (e.g. after pressing the home button and just clicking the app icon again without killing the app inbetween).
But I do NOT want to do this, when the device is rotated.
For example, I have a method:
private void scrollToNow() {
// do the calculation and scroll all views to the correct position
// this is code I already have fully functional!
}
And I want to execute it every time the activity gets active again, but NOT on orientation change.
I tried a lot of combinations (in onStart, onResume, onCreate), but none of them did the trick. I tried to build a solution using the savedInstanceState but failed.
Anybody got some tips or useful links for me?
Thanks alot,
Oliver
Please, think twice before you decide to check configuration changes manually.
If your application doesn't need to update resources during a specific configuration change and you have a performance limitation that requires you to avoid the activity restart, then you can declare that your activity handles the configuration change itself, which prevents the system from restarting your activity.
Note: Handling the configuration change yourself can make it much more difficult to use alternative resources, because the system does not automatically apply them for you. This technique should be considered a last resort when you must avoid restarts due to a configuration change and is not recommended for most applications.
Try to save some flag in onSaveInstanceState and in onCreate check if there is savedInstanceState, then save it as field for example. This will give you information about does activity is 'recreated' or not. Then in 'onResume' check is this flag set or not. If not, then you are not 'recreated' your activity, so you can invoke scrollToNow()
I dont want to recreate layout when screen orientation change
Did you tried to add this line to your AndroidManifest.xml android:configChanges="screenLayout|screenSize|orientation" like that :
<activity
android:name="youractivity"
android:configChanges="screenLayout|screenSize|orientation"
android:label="#string/title_activity_create_note"
android:theme="#style/AppTheme"
android:windowSoftInputMode="stateAlwaysHidden" />
For more information you can take a look at : manifest/activity-element in that page go to android:configChanges section and read please .
When adding this you must handle onConfigurationChanged() method by yourself instead of Android System.
Please read carefully Note section in that page :
Note: Using this attribute should be avoided and used only as a last resort. Please read Handling Runtime Changes for more information about how to properly handle a restart due to a configuration change.
Also i am using this in my application maybe you can try this too : android:screenOrientation="nosensor" in that page you can find information about it too.

Android - problems with a multi-level activity chain

(Note that I've searched online for the warnings I'm describing below, and have come up with next to nothing about them.)
I'm working with API level 10. I have a preference screen (XML-based), and one of the options in there creates a custom ListActivity as follows:
PreferenceActivity contains an option that creates a...
ListActivity which is a dialog that employs...
setOnClickListener() which contains an onClick() method that (right before calling finish()) will startActivity() a new Intent...
sub-Activity which starts up an...
AsyncTask which does variable time work which when done calls...
onPostExecute() which calls finish()
The thing is, it works... but I'm getting a raft of warning starting with:
10-16 21:59:25.010: WARN/WindowManager(170): Rebuild removed 4 windows but added 3
10-16 21:59:25.010: WARN/WindowManager(170): This window was lost:.....
Curiously, this raft of warnings ONLY comes up when the task executes quickly! When I added a Thread.sleep() call to my AsyncTask to artificially inflate its runtime it worked and threw no warnings whatsoever. In fact, as long as it takes more than (roughly) 500 ms to run it works fine. (Note that I tried using startActivityForResult() to no greater effect - the same problem occurs.)
The goal is that the user selects a preference item, they change its setting, some processing takes place, and then the user is left back at the preference menu they started on.
I'm betting it's a race condition... the order in which the windows are destroyed varies depending on that run-time... and I get the impression that when the sub-Activity closes before its parent ListActivity the warnings get thrown. But sprinkling a 1s sleep() in isn't a reasonable solution unless this is some sort of Android bug (unlikely, but then again I've reproduced a couple of those today already).
So, what's the flaw in this my that leads to this stream of warnings? It'd be nice to say "on preference, do this, then do that, then finish" but I think what I'm doing is the equivalent. Maybe not... thoughts?
Edit: I decided to try doing this ListActivity as a custom Dialog... that was one of the more painful things I've tried to do lately (getApplication() doesn't work and lots of other things seem to go wrong... it may be inexperience to some extent, but dialogs really weren't meant for this either...
Try the following two things:
Dismiss your dialog before calling finish() on its parent activity (PreferenceActivity).
Make sure you are starting your AsyncTask later in the sub-activity's lifecycle. I'm specifically thinking you should launch it in onResume().
My best guess is that the AsyncTask is calling finish() on the sub-activity, before the sub-activity has had a chance to fully start up. Why that would matter? I'm not sure. Something to try though. Good luck!

ResourceNotFound on layout inflation

My app may launch a sub-activity for a specific purpose. When that activity finishes, I get the results in onActivityResult. These results are then processed in the subsequent onResume. This consists of a setContentView and also starting an AsyncTask that puts up a ProgressDialog.
This all works well when initiated the normal way, which is via a user request (i.e., menu selection) after the app is up and running. However, under some conditions I need to do this right as the app is starting up, so I initiate this sequence right from my onCreate. What then happens is that I get fatal ResourceNotFound errors within any o/s call that implicitly calls the layout inflater. I got around this with setContentView by pre-inflating the view in my onCreate method, but the AsyncTask's onPreExecute still fails on ProgressDialog.show() as it "fails to find" Android's own progress_dialog.xml!
Anyone know what's happening here?
I suspect it's something to do with the timing, where this is occurring before the main activity has even had a chance to display its screen. These calls are all being made on the main UI thread, but maybe something hasn't completed within the o/s under these conditions.
As a closeout, the problem turned out to be totally unrelated to what I described in my post. Turns out it was due to blindly using some code that had been posted in some online forum showing how to get and use AssetManager. Trouble is, at the end of the block of code he had put "assMan.close()". Well, this closes the asset manager for the entire activity and resources can no longer be accessed!
It took a while to find it since it was not something that I did via my own understanding.

Categories

Resources